Stacks

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

Updated 9 min read

To trace an Elixir runtime bug from a stack trace with Atlas, paste the trace and let Atlas read each frame's file at the reported offset. An Elixir stack trace is a list of file:line pairs pointing into lib/, which is exactly what Atlas's read tool consumes. Offsets are validated against the current file, so a trace from an older release fails loudly with Offset <n> is out of range for this file instead of pointing at the wrong code. Grep for the error message string to find where it is constructed, which is usually more informative than the top frame, use the lsp tool's findReferences operation to see which callers can reach the failing function, then fix with edit and add an ExUnit regression test run with ExUnit via mix test.

How do you trace an Elixir runtime bug from a stack trace with Atlas?

Atlas traces an Elixir runtime bug by reading each stack frame at its reported offset, step 1 of the 5 step debugging workflow. An Elixir trace is a list of file:line pairs, typically pointing into lib/my_app/accounts.ex or a GenServer under lib/my_app/workers, and Atlas's read tool consumes exactly that format without a debugger attached.

Paste the trace into an Atlas session running in a project with a mix.exs, let Atlas read your supervision tree, contexts, and deps, and the first move is mechanical: read each frame's file at the offset it names. Atlas indexes code by AST declarations using tree-sitter, not blind line windows, so reading a frame inside a GenServer's handle_call clause returns the whole clause rather than a slice that starts mid-pattern-match. In Elixir the top frame is often the least useful one, because a FunctionClauseError or a MatchError is raised where the bad value arrived, not where it was created. Reading the frames in order is how you find the boundary between those two places.

What does Offset is out of range mean when Atlas reads an Elixir file?

When Atlas's read tool reports Offset <n> is out of range for this file, the Elixir stack trace came from a different build. Offsets are validated against the current file, so a trace from a release deployed three weeks ago fails loudly rather than pointing you at whatever now happens to sit at line 214 of lib/my_app/accounts.ex.

A stale trace is one of the most expensive kinds of debugging mistake, because everything you conclude from it is confidently wrong. Atlas refuses to make that mistake silently. If read reports Offset <n> is out of range for this file, re-read the file from the top before trusting any line number, and check out the tag or the commit that actually produced the release if you can. Elixir compounds this: a hot-upgraded release or a codebase that has been through a `mix format` pass since the crash will have shifted line numbers even when the logic is identical. The loud failure is the feature. Atlas reads git branches, status, and diffs, so pinning the review to the right commit is straightforward.

Why does Atlas grep for the Elixir error message instead of trusting the top frame?

Atlas greps for the error message string at step 3 to find where it is constructed, which is usually more informative than the top frame of an Elixir trace. A raise in lib/my_app/billing.ex, an `{:error, :invalid_state}` tuple, or a custom exception defined with defexception is where the real intent lives.

Elixir errors are frequently constructed far from where they surface. A `with` chain collapses several failure paths into one `else` clause. A GenServer call that times out reports the caller's frame, not the server's. A custom exception defined with defexception carries a message built somewhere entirely different from the module that raised it. Grepping the literal message string across lib/ jumps straight to the construction site. Atlas searches code with hybrid semantic and keyword retrieval fused by reciprocal rank fusion through codebase_search when the question is conceptual, such as where this context validates state transitions, and grep when the question is a literal string. In Elixir debugging you want both, in that order.

How do you find which Elixir callers can reach a failing function?

Atlas uses the lsp tool's findReferences operation on the failing Elixir function to see which callers can reach it with the bad input. A private function in lib/my_app/accounts.ex might have 6 callers, and only 2 of them can pass the unvalidated map that produced the MatchError in the trace.

A stack trace shows one path. findReferences shows all of them, which is what you need to know whether you are fixing a symptom or a cause. Ask the language server for the callers of the function in the top frame, then work outward: which of those callers validates its input, which passes a raw map straight from a Phoenix controller, which is invoked from a Task or a GenServer where the caller's own context is lost. Atlas fans out work to subagents that can run in the foreground or in parallel background sessions, so a wide caller sweep across a large umbrella project can run in the background while the main session stays on the failing module. Mix and Hex give you the dependency boundary, and findReferences tells you whether the bad input crossed it.

How do you fix an Elixir bug and prove it cannot recur?

Atlas fixes the Elixir bug with the edit tool and adds a regression test, step 5 of the workflow, so the trace cannot recur silently. Run ExUnit via mix test to prove the new test fails before the fix and passes after, then run mix format on the touched files so the diff shows the behavior change and nothing else.

The regression test is the step that turns a fix into a permanent one. Write an ExUnit case that reproduces the exact input from the trace, run ExUnit via mix test to watch it fail against the unfixed code, then apply the edit. Atlas computes a unified diff for every file edit and surfaces it for approval before writing, so the change to lib/my_app/accounts.ex is visible before it lands. Atlas snapshots file changes as git patches so edits can be diffed and rolled back if the fix turns out to address the wrong frame. Let Mix and Hex resolve any dependency the fix required, run mix format, and the change is ready to review.

Step by step

  1. 01Run atlas in a project with a mix.exs and let Atlas read your supervision tree, contexts, and deps.
  2. 02Paste the Elixir stack trace and have Atlas read each frame's file at the reported offset, since the trace is already a list of file:line pairs into lib/.
  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 error message string across lib/ to find where it is constructed, which is usually more informative than the top frame of the trace.
  5. 05Use the lsp tool's findReferences operation on the failing function to see which callers can reach it with the bad input.
  6. 06Write an ExUnit regression test that reproduces the exact input from the trace, and run ExUnit via mix test to watch it fail first.
  7. 07Fix the bug with the edit tool, approving the unified diff Atlas surfaces before it writes to lib/.
  8. 08Re-run ExUnit via mix test through the bash tool to confirm the regression test now passes and nothing else broke.
  9. 09Run mix format on the touched Elixir files, and let Mix and Hex resolve any dependency the fix required.

Frequently asked questions

How do I debug an Elixir stack trace without attaching a debugger?
Paste the trace into Atlas and have it read each frame's file at the reported offset. An Elixir trace is a list of file:line pairs, which is exactly what Atlas's read tool consumes, so the responsible code is on screen without a debugger attached.
What does Offset is out of range for this file mean in Atlas?
The stack trace came from a different build than the code on disk. Atlas validates offsets against the current file, so a trace from an older Elixir release fails loudly rather than pointing at the wrong line. Re-read the file from the top before trusting any line number.
Why is the top frame of an Elixir stack trace often misleading?
In Elixir a MatchError or FunctionClauseError is raised where the bad value arrived, not where it was created. Grep for the error message string to find where the error is constructed, which is usually more informative than the top frame.
How do I find every caller of a failing Elixir function?
Use the lsp tool's findReferences operation in Atlas. It asks the language server for the caller set, so you can see which callers pass unvalidated input into the function that raised, rather than only the one path the trace happened to record.
Does Atlas run mix test on an Elixir project?
Atlas runs ExUnit via mix test through its bash tool once the command is allowed by your permission rules. Run the regression test before the fix to watch it fail, then after the fix to prove the bug is closed.
Can Atlas work with a Mix umbrella project?
Run atlas in a project with a mix.exs and Atlas reads your supervision tree, contexts, and deps. Atlas also fans out work to subagents that can run in parallel background sessions, which is useful for sweeping callers across a large umbrella.
Will Atlas run mix format after fixing an Elixir bug?
Yes, through the bash tool. Running mix format on only the touched files keeps the diff focused on the behavior change instead of mixing it with formatting.
How do I undo an Elixir fix Atlas applied?
Atlas snapshots file changes as git patches so edits can be diffed and rolled back. It also computes a unified diff for every file edit and surfaces it for approval before writing, so nothing lands in lib/ without you seeing it.

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

Adopt Atlas, the terminal-native AI coding agent, for Elixir development in 2026. Enhance productivity with deep code understanding, safety features, and direct integration into mix projects and OTP applications.

Write Unit Tests for Untested Code in Elixir with Atlas in 2026

Learn how Atlas helps Elixir developers in 2026 add robust unit tests to untested modules, matching existing repo conventions using ExUnit via mix test.

Review a Pull Request in Elixir with Atlas in 2026

Streamline your Elixir pull request reviews in 2026 with Atlas. Leverage AI to fetch diffs, analyze full files, check mix.exs dependencies, and run ExUnit via mix test for comprehensive bug detection.

Rename a symbol across the repo in Elixir with Atlas in 2026

Effortlessly rename Elixir functions, modules, or constants across your entire codebase in 2026 using Atlas. Leverage `lsp`, `grep`, and `edit` for precise, verified refactoring, ensuring your `mix test` suite remains

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

Plan a multi-file Elixir change before editing with Atlas in 2026. Plan mode denies all edit tools, so you research contexts and GenServers and design the change first.

Run the Test Suite and Triage the Failures in Elixir with Atlas (2026)

Triage a red ExUnit suite in Elixir with Atlas in 2026. Run mix test through bash, read the retained log past the 2000-line truncation, and group causes with grep.

Refactor a legacy module in Elixir with Atlas in 2026

Refactor Elixir modules safely in 2026 with Atlas, the terminal-native AI coding agent. Pin behavior with ExUnit via mix test, map callsites with LSP, and apply changes with atomic patches.

Browse this resource hub