Stacks

Trace a runtime bug from a stack trace in Java with Atlas (2026)

Updated 9 min read

To trace a runtime bug from a Java stack trace with Atlas, paste the trace and let Atlas read each frame at its reported offset. A Java stack trace is a list of file:line pairs, at com.example.billing.InvoiceService.total(InvoiceService.java:142), which is exactly what Atlas's read tool consumes. Atlas reads each frame at the offset, greps for the exception message string to find where it is constructed (usually more informative than the top frame), and uses the lsp tool's findReferences operation on the failing method to see which callers can reach it with the bad input. Offsets are validated against the current file, so if read reports Offset <n> is out of range for this file, the trace came from a different build and you must re-read the file from the top before trusting any line number. Atlas fixes with edit and adds a JUnit 5 test so the trace cannot recur silently, then Maven runs JUnit 5 via mvn test and Spotless normalizes the diff.

How does Atlas read a Java stack trace?

Atlas consumes a Java stack trace as a list of file:line pairs. A frame like at com.example.billing.InvoiceService.total(InvoiceService.java:142) tells Atlas's read tool exactly which file and which offset to open, so in 2026 you paste the trace and Atlas reads each frame at its reported line rather than guessing at the file.

Java stack traces are unusually machine-friendly, and Atlas exploits that. Each frame carries the fully qualified class name, the method, the simple file name, and the line number, so mapping com.example.billing.InvoiceService to src/main/java/com/example/billing/InvoiceService.java is mechanical in any Maven layout. Atlas reads each frame at its offset, walking down from the throw site through the callers the JVM recorded. Where the trace passes through framework frames, a Spring proxy, a servlet filter, a Hibernate interceptor, Atlas skips to the next frame in your own package, because those are the ones you can act on. Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so the method the frame lands in comes back whole.

What if the Java line numbers do not match the source?

If Atlas's read tool reports Offset <n> is out of range for this file, the Java stack trace came from a different build. Re-read the file from the top before trusting any line number. A trace produced by a JAR built 12 commits ago will point confidently at the wrong method.

Stale-trace debugging is the most wasteful failure mode in Java, and Atlas is built to fail loudly on it. Offsets are validated against the current file, so a trace from an older build fails loudly instead of pointing at the wrong code. In practice, a production Java stack trace almost always comes from a JAR built from an older commit than your working tree, which means InvoiceService.java:142 in the trace may now be a blank line or a different method entirely. When read raises Offset out of range, or when the method at that line is obviously not the one in the frame, Atlas re-reads the file from the top and locates the method by name instead of by offset. Atlas reads git branches, status, and diffs, so you can also check what changed between the deployed commit and HEAD.

Why grep the Java exception message instead of the top frame?

Atlas greps for the error message string to find where it is constructed, which in 2026 is still more informative than the top frame. In Java the top frame is often a utility like Objects.requireNonNull or a Guava Preconditions.checkArgument, while the message string invoice must have at least one line item appears exactly once, at the real check.

The top frame of a Java stack trace tells you where the exception was thrown, not where the decision was made. An IllegalArgumentException thrown from Preconditions.checkArgument names Preconditions.java, which is not your code and not your bug. The message string, though, is a unique literal in your source, and grepping for it lands directly on the validation that failed. The same is true for a custom exception: grep for the message passed to new InvoiceValidationException(...) and you are at the branch that decided the input was bad. Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion, so even a message assembled from a format string can be located by concept when the literal grep misses.

How do you find which Java callers can reach a failing method?

Atlas uses the lsp tool's findReferences operation on the failing method to see which callers can reach it with the bad input. In 2026 a Java stack trace still shows only 1 path to the failure, while findReferences shows all of them, which is how you learn that InvoiceService.total is also called from a nightly batch job the trace never mentions.

A stack trace is one witness, not the population. The trace proves that one caller reached the failing method with bad input; findReferences tells you which other callers could. In a Java service that matters because the fix depends on the answer: if only the REST controller can pass a null customer, validate in the controller. If a Kafka consumer, a scheduled @Scheduled job, and a REST controller can all reach InvoiceService.total, the guard belongs in the method itself. Atlas runs findReferences through the Java language server, which resolves the interface implementations and the Spring injection points that a grep for the method name would either miss or over-match.

How do you make sure a Java bug cannot recur?

Atlas fixes the bug with edit and adds a JUnit 5 regression test so the trace cannot recur silently. In a 2026 Maven project the test lands under src/test/java/, reproduces the exact input from the stack trace, and is proven by running JUnit 5 via mvn test, which must fail before the fix and pass after it.

The regression test is what converts a traced bug into a fixed one. Write a JUnit 5 test under src/test/java/com/example/billing/InvoiceServiceTest.java that constructs the exact input the trace implies, assert the correct behavior, and run JUnit 5 via mvn test to see it fail. Then apply the fix with edit and re-run mvn test to see it pass. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so the change to InvoiceService.java is reviewed before it lands, and Atlas snapshots file changes as git patches so edits can be diffed and rolled back. Run Spotless so the formatting matches the project, then let Maven build the module and Atlas stage the commit.

Step by step

  1. 01Run atlas in a project with a pom.xml or build.gradle so Atlas can read your packages, classpath, and build configuration.
  2. 02Paste the Java stack trace and have Atlas read each frame's file at the reported offset, mapping com.example.billing.InvoiceService to src/main/java/com/example/billing/InvoiceService.java.
  3. 03If read reports Offset <n> is out of range for this file, the trace came from a different build; re-read the file from the top before trusting any line number.
  4. 04Grep for the exception message string to find where it is constructed, which is usually more informative than a top frame sitting in Objects.requireNonNull or Preconditions.
  5. 05Use the lsp tool's findReferences operation on the failing method to see which callers can reach it with the bad input, including scheduled jobs and consumers the trace never mentions.
  6. 06Write a failing JUnit 5 test under src/test/java/ that reproduces the exact input from the trace, and prove it fails with JUnit 5 via mvn test.
  7. 07Fix with edit, reviewing the unified diff Atlas surfaces before it writes to the .java file.
  8. 08Re-run JUnit 5 via mvn test to confirm the regression test now passes, then run Spotless and let Maven rebuild the module before committing.

Frequently asked questions

how to debug a Java stack trace without attaching a debugger
Paste the trace into Atlas. A Java stack trace is a list of file:line pairs, which is exactly what Atlas's read tool consumes: it reads each frame at its offset, greps for the exception message string, and uses the lsp tool's findReferences to find callers that can reach the failing method.
why do my Java stack trace line numbers point at the wrong code
The trace almost certainly came from a JAR built from an older commit. Atlas validates offsets against the current file, so if read reports Offset <n> is out of range for this file, re-read the file from the top and locate the method by name rather than by line number.
what is the fastest way to find where a Java exception is thrown
Grep for the exception message string rather than reading the top frame. A top frame in Objects.requireNonNull or Guava Preconditions is not your code, but the message literal appears exactly once, at the validation that actually failed.
how do I know which callers can trigger a Java NullPointerException
Run Atlas's lsp tool findReferences operation on the failing method. The stack trace shows one path; findReferences shows all of them, including the @Scheduled batch job or Kafka consumer the trace never mentions, which decides where the guard belongs.
does Atlas work with Maven and Gradle Java projects
Yes. Run atlas in a project with a pom.xml or build.gradle. Atlas reads your packages, classpath, and build configuration, and can add JUnit tests or refactor a class hierarchy, showing you the diff before anything is written.
how do I write a regression test for a Java production bug
Write a JUnit 5 test under src/test/java/ that reproduces the exact input the stack trace implies, run JUnit 5 via mvn test to confirm it fails, then apply the fix with edit and re-run mvn test to confirm it passes.
can I roll back an AI fix to a Java class
Yes. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, and Atlas snapshots file changes as git patches so edits can be diffed and rolled back if the fix turns out to be wrong.

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 Java in 2026

Adopt Atlas, the terminal-native AI coding agent, for Java development in 2026. Enhance your workflow with intelligent code search, refactoring, and robust safety features for Maven and Gradle projects.

Self-Review Your Working Diff Before Committing in Java with Atlas (2026)

Self-review an uncommitted Java diff with Atlas in 2026. Read every changed class, grep for debug leftovers, revert from snapshots, then run JUnit 5 via mvn test.

Review a Pull Request in Java with Atlas (2026)

Atlas reviews a Java pull request by pulling the raw diff with bash, reading changed classes in full, and running the lsp tool's findReferences on every changed signature.

Document a Java Module with a README using Atlas in 2026

In 2026, Atlas helps Java developers create accurate, up-to-date README documentation for modules. It leverages Maven, JUnit 5, and Spotless to reflect current code behavior.

Add a Regression Test for a Java Bug Fix with Atlas (2026)

Lock a Java defect down in 2026 with a test that goes red before the fix and green after. Atlas proves both states from the real exit code, then patches with edit.

Plan a Multi-File Change Before Editing in Java with Atlas (2026)

Plan a Java refactor with Atlas in 2026 before touching src/main/java: plan mode denies edits, the lsp tool maps the class hierarchy, and plan_exit gates the handoff.

Debug a Single Failing Test in Java with Atlas (2026)

Fix the code, not the assertion. Atlas runs one JUnit 5 test in isolation via mvn test in 2026, walks the call path with the lsp tool, and edits the Java that is wrong.

Browse this resource hub