# Capture warnings with Code.with_diagnostics/2

Use `Code.with_diagnostics/2` when warnings and errors need to become structured data instead of terminal text.

```elixir
source = ~S"""
defmodule Price do
  def total(items) do
    count = length(items)
    Enum.sum(items)
  end
end
"""

{_compiled, diagnostics} =
  Code.with_diagnostics(fn ->
    Code.compile_string(source, "price.ex")
  end)

Enum.map(diagnostics, fn diagnostic ->
  first_line = diagnostic.message |> String.split("\n") |> hd()
  {diagnostic.severity, diagnostic.position, first_line}
end)

# => [
#      {:warning, {3, 5},
#       "variable \"count\" is unused (if the variable is not meant to be used, prefix it with an underscore)"}
#    ]
```

Each diagnostic is a map containing fields such as `:severity`, `:message`, `:file`, `:position`, and `:stacktrace`, with optional span and detail data. That makes the result suitable for editor annotations, code-generation checks, or tests around dynamically compiled code.

Diagnostics are not printed by default while they are captured. Pass `log: true` when you want both structured results and the normal log output.

`Code.with_diagnostics/2` does not rescue exceptions raised inside the function. Wrap the compilation in `try/rescue` if both the exception and the captured diagnostics must be returned as data. `mix compile` and `Kernel.ParallelCompiler` already capture diagnostics themselves.

[Code.with_diagnostics/2 docs](https://hexdocs.pm/elixir/Code.html#with_diagnostics/2)


---

Created by: almirsarajcic
Date: September 05, 2026
URL: https://elixirdrops.net/d/N8vneTPL
