Guide
Diagnostics
Read compiler locations and codes, isolate a failing stage, and inspect the module graph.
Diagnostic shape
A diagnostic prints its severity, stable domain code, source location, and message. Codes identify the owning compiler stage: lex-*, parse-*, res-*, sem-*, or cg-*.
error[sem-unbound] src/main.echo:8:12: unbound name `total`
Normal workflow
xo fmt --check src/main.echo
xo check src/main.echo
xo check --graph src/main.echo
xo check --diag-codes src/main.echo
xo ir src/main.echo
Start with xo check because it resolves the full import graph and runs semantics without linking a binary. --graph prints resolved modules; --diag-codes emits only codes for scripts and fixture-style assertions.
Isolate the stage
xo lex --kinds --diag-codes src/main.echo
xo ast --kinds --diag-codes src/main.echo
xo ir --diag-codes src/main.echo
If lexing fails, later stages have no trustworthy source structure. When AST output succeeds and check fails, focus on names, kinds, effects, and module rules. IR emission also exercises HIR, MIR, and LLVM code generation. The IR includes DWARF line locations from source spans and local-variable kinds from the checker.
Common semantic codes
sem-unbound name is not available at this point
sem-shadow name is introduced twice in one region
sem-immutable write targets an immutable binding or field
sem-type-mismatch incompatible kinds or numeric widths
sem-not-callable call target is not a function value
sem-arity argument count does not match
sem-unhandled-result result must be matched with $ / ! arms
sem-unhandled-option option must be matched with $ / : arms
sem-task-capture capture does not name an existing binding
sem-task-arity task call or capture list exceeds the ABI limit
Common resolver codes
res-entry entry file is missing or invalid
res-import import cannot be resolved
res-import-name-conflict two imports bind the same final segment
res-import-cycle module graph contains a cycle
res-export-missing exported name is not defined
res-runtime-forbidden userland attempted / runtime
res-struct-dup-primary multiple % declarations for one struct
res-struct-no-primary @ members have no matching % declaration
res-struct-dup-member merged struct members collide
Cache checks
When a local toolchain or std source has changed and output appears stale, bypass artifacts once with --no-cache or inspect them with xo cache status and xo cache doctor. Cache cleaning should be a diagnosis step, not a substitute for fixing a source error.