Stacks

Trace a Runtime Bug From a Stack Trace in Kotlin with Atlas (2026)

Updated 8 min read

To trace a runtime bug from a stack trace in Kotlin, paste the trace into Atlas and have it read each frame's file at the reported offset. A Kotlin stack trace is a list of file:line pairs, `at com.example.OrderService.process(OrderService.kt:42)`, which is exactly what Atlas's read tool consumes. Atlas reads each frame at its offset, uses grep to find the callers the trace does not show, and reconstructs the path. Offsets are validated against the current file, so a trace captured from an older Gradle build fails loudly instead of pointing at the wrong code. The fix lands with edit and is locked in with a JUnit 5 via gradle test regression case.

How does Atlas read a Kotlin stack trace?

A Kotlin stack trace is a list of file:line pairs, and Atlas's read tool consumes exactly that. Paste a JVM trace whose top frame is `at com.example.OrderService.process(OrderService.kt:42)` and Atlas reads `OrderService.kt` at offset 42, then walks down the frames one at a time.

Kotlin traces have quirks that reward reading frames rather than skimming them. Coroutine frames are interleaved with suspension markers, synthetic frames from inline functions appear with odd names, and the useful frame is often several lines below the top. Atlas reading each frame at its reported offset means the actual source of `OrderService.kt:42` is in context, including the surrounding function body, rather than a guess about what a method with that name probably does. Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so it can also tell you which declaration in `OrderService.kt` contains line 42.

Why does Atlas say Offset is out of range for my Kotlin file?

Atlas reports Offset <n> is out of range for this file when the Kotlin stack trace came from a different build than the one on disk. Re-read the file from the top before trusting any line number, because a trace captured from a release built 2 weeks ago points at lines that have since moved in OrderService.kt.

Stale traces are the quiet killer of stack-trace debugging, and Atlas is built to fail loudly on them rather than silently mislead. Offsets are validated against the current file, so a line number past the end of the file is rejected outright. In a Gradle project this happens constantly, because the trace usually arrives from a production deployment while your working tree has moved on. When read refuses the offset, stop trusting line numbers entirely and switch to symbol-based navigation: find the function named in the frame, not the line number attached to it.

How do I find where a Kotlin exception message is actually constructed?

Atlas greps for the error message string to find where it is constructed, which is step 3 of the documented trace workflow and usually more informative than the top frame of a Kotlin stack trace. A message like order total must be positive appears at exactly 1 require or check callsite, and that callsite names the violated invariant.

Kotlin idioms make this productive. `require`, `check`, `error`, and `checkNotNull` all carry a literal message, so grepping the message text lands directly on the line that threw. For a NullPointerException from a `!!` operator there is no message, so grep for the property name from the frame instead. Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, so when the exact string is constructed through interpolation and a literal grep fails, semantic retrieval still surfaces the throwing code.

How do I find which callers can reach a failing Kotlin function?

Use the lsp tool's findReferences operation on the failing Kotlin function to see which callers can reach it with the bad input. A stack trace shows one path; findReferences on `process` in `OrderService.kt` shows all 9 of them, including the coroutine launch site the trace flattened away.

The trace is a single observed path, not the set of possible paths. In Kotlin this gap is wider than usual because coroutine dispatch breaks the caller chain: the frame that launched the coroutine may not appear at all. findReferences restores the picture by listing every callsite of the function that threw. Reading those callsites is how you learn which one passes the null, the negative total, or the unvalidated string. Combine it with grep over the module to catch callers reached through an interface that the language server resolves differently.

How do I fix a Kotlin runtime bug so the trace cannot recur?

Fix the responsible line with Atlas's edit tool and add a JUnit 5 regression test so the stack trace cannot recur silently. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so the change to `OrderService.kt` is reviewed as a patch, never applied blind.

The fix and the test belong in the same change. Add a test under `src/test/kotlin` that reproduces the exact input from the trace, run it with JUnit 5 via gradle test, and confirm it fails before the fix and passes after. Run ktlint so the new file matches the project's Kotlin style rather than introducing formatting drift into a bug-fix commit. Atlas snapshots file changes as git patches, so if the fix turns out to be wrong the edit can be diffed and rolled back rather than hand-reverted. Every Atlas tool call is permission-gated against allow, ask, and deny rules before it runs, so `gradle test` can be allowed while writes stay on ask.

Step by step

  1. 01Paste the Kotlin stack trace into Atlas and have it read each frame's file at the reported offset, starting from `at com.example.OrderService.process(OrderService.kt:42)`.
  2. 02If read reports Offset <n> is out of range for this file, the trace came from a different Gradle build; re-read the file from the top before trusting any line number.
  3. 03Grep for the error message string to find where it is constructed, since Kotlin's require, check, and checkNotNull all carry a literal message that lands on the throwing line.
  4. 04Use the lsp tool's findReferences operation on the failing Kotlin function to list every caller, including the coroutine launch sites the flattened trace hides.
  5. 05Read the suspect callsites and identify which one supplies the bad input, such as the null behind a `!!` or the negative value behind a require.
  6. 06Fix the responsible line with the edit tool and review the unified diff Atlas surfaces before it writes to `OrderService.kt`.
  7. 07Add a regression test under `src/test/kotlin` and run it with JUnit 5 via gradle test, confirming it fails before the fix and passes after.
  8. 08Run ktlint so the new Kotlin file matches project style, then re-run the Gradle build to confirm nothing else broke.

Frequently asked questions

how to debug a kotlin stack trace without a debugger
Paste the trace into Atlas and let its read tool open each frame at the reported offset, for example `OrderService.kt:42`. Grep the error message to find where it is constructed, then use the lsp findReferences operation on the failing function to see which callers can reach it with the bad input.
atlas offset is out of range for this file
That message means the stack trace came from a different build than your working tree. Atlas validates offsets against the current file, so it fails loudly rather than reading the wrong lines. Re-read the file from the top and navigate by symbol name instead of line number.
kotlin coroutine stack trace missing caller
Coroutine dispatch breaks the caller chain, so the frame that launched the coroutine may not appear in the trace at all. Use the lsp tool's findReferences operation on the failing function to enumerate every callsite, including the launch site the trace flattened away.
how do i find where a kotlin exception message comes from
Grep for the message string. Kotlin's require, check, error, and checkNotNull all take a literal message, so the text lands directly on the throwing line, which is usually more informative than the top frame of the trace.
kotlin nullpointerexception from !! how to trace
A `!!` throws with no message, so grep for the property name from the frame instead of the message text. Then read the frame at its offset and use findReferences to see which caller supplies the null.
does atlas edit my kotlin file without asking
No. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, and every tool call is permission-gated against allow, ask, and deny rules before it runs.
how do i stop a kotlin bug from regressing
Add a regression test under `src/test/kotlin` that reproduces the exact input from the stack trace, run it with JUnit 5 via gradle test to confirm it fails before the fix, then apply the fix and confirm it passes.
can atlas roll back a kotlin fix that was wrong
Yes. Atlas snapshots file changes as git patches, so an edit to a Kotlin file can be diffed and rolled back rather than hand-reverted. Run ktlint after the final version so the commit does not carry style drift.

Try Atlas in your terminal

The terminal-native AI coding agent. Free core, single binary.

Install Atlas

Related guides

Trace a Runtime Bug from a Stack Trace with Atlas in 2026

How to trace a runtime bug from a stack trace with Atlas in 2026: read each frame at its offset, grep for the error string, and use the lsp tool to find callers.

Atlas for Kotlin in 2026

In 2026, Atlas empowers Kotlin developers with terminal-native AI coding. It integrates with Gradle and coroutines, offering secure, privacy-focused code assistance with local embeddings and granular control.

Automate GitHub Issue and Pull Request Triage in Kotlin with Atlas in 2026

Automate GitHub issue and pull request triage in Kotlin with Atlas. Learn how Atlas integrates with Gradle and ktlint to safely manage PRs and issues for trusted users in 2026.

Run the test suite and triage the failures in Kotlin with Atlas (2026)

How Atlas runs a Kotlin test suite and triages failures in 2026: bash truncates at 2000 lines, retains the full log, and grep groups 60 red tests into distinct root causes.

Add a Regression Test for a Kotlin Bug Fix with Atlas in 2026

Lock in Kotlin bug fixes with Atlas in 2026. Learn to write failing JUnit 5 tests via Gradle, apply fixes, and confirm success, all within your terminal.

Extract a Shared Helper from Duplicated Kotlin Code with Atlas in 2026

Streamline your Kotlin codebase in 2026 by extracting duplicated logic into a single, tested helper using Atlas. Leverage Gradle, JUnit 5, and ktlint for robust refactoring.

Atlas: Documenting Kotlin Modules with READMEs in 2026

Leverage Atlas in 2026 to generate accurate READMEs for your Kotlin modules. Atlas uses Gradle and JUnit 5 to document what your code actually does today, not what it was supposed to do a year ago.

Research a Third-Party API Before Integrating It in Kotlin With Atlas (2026)

How to research a third-party API before integrating it in Kotlin with Atlas in 2026: websearch finds the docs, webfetch pulls them, and every request is permissioned.

Browse this resource hub