Collect errors instead of throwing
Gather every problem in one pass with `collect: true` (TypeScript) or `Check` (Go) instead of stopping at the first.
Rendered from
docs/how-to/collect-errors.md
in the engine repository, where a correction belongs, and where the
test suite executes every example on this page.
generate throws on the first surfaced error, which suits a build
step and fails a linter: an editor wants every problem in one pass,
each with its location. Pass collect: true and read the result’s
err array:
const aontu = new Aontu()
const res = aontu.unify('a: 1 a: 2', { collect: true })
res.err // one NilVal per failure — nothing thrown
res.err[0].why // 'scalar_value', the error code
res.canon // '{"a":nil}' — the failure sits where it happened
Each collected error is a NilVal: the value a failed unification
leaves behind, carrying its error code (why), its full message, and
the path it failed at. The rest of the document still unifies around
it, which is what makes the mode useful: one pass, every error,
each located. The canonical form then shows
nil at each failed path, a map of the damage.
The Go port never throws for a conflict (Unify and Generate
return an error), but that error is still the first one. The
every-problem call is Check:
problems := aontu.New().Check("a:1\na:2")
// every problem: source position, error code, full message
Both language servers are this mode with a protocol around it: the
diagnostics your editor shows are a walk over the collected NilVals
(how diagnostics are
computed). A valid but
non-concrete document (a schema, a partial fragment) collects
nothing: a value still waiting for information is a residual, not an
error.
The collect and err options are in
AontuOptions. To make sense of
one collected conflict, read a conflict
error; to get the collecting behaviour in
your editor rather than your code, wire your
editor.