Wit

Errors reference

Errors are the developer's contract with the pipeline. There are two typed families, both carrying a stable, switchable .code and a .loc. This page lists every code, the stage that throws it, and the fix.

The two families

  • Parse — WitError (thrown as its subclass ParseError), .code: ErrorCodeName, 20 codes. Thrown by parse.
  • Runtime — RuntimeError (base), with subclasses ResolverError (resolve) and ExpanderError (expand), .code: RuntimeErrorCodeName, 17 codes. RuntimeErrorCode is exported for switching.

Both extend the same shape, so one instanceof per family catches everything:

import { WitError } from '@witlang/parser';
import { RuntimeError } from '@witlang/runtime';

try { /* parse → resolve → expand → render */ }
catch (err) {
  if (err instanceof WitError || err instanceof RuntimeError) {
    console.error(`${err.loc.line}:${err.loc.col}: ${err.code}: ${err.message}`);
  } else throw err;
}

Parser codes — WitError

All thrown during parse. Cause and fix for each:

  • E_UNCLOSED_NODE — a use that opens a block never closes (@aside on its own line, no aside@). Only uses that take a body need a close. Fix: add the close.
  • E_UNCLOSED_COMMENT — a ~~ block comment without ~~/. Close it.
  • E_UNCLOSED_DEFINITION — a #name block without its name#, or a value block without !!.
  • E_UNCLOSED_PAREN — a @x( parameter list not closed before the next blank line. Add the ).
  • E_UNCLOSED_STATEMENT — (if …) or (each …) without (end).
  • E_UNCLOSED_COLLECTION, E_UNCLOSED_SCRIPT, E_UNCLOSED_RAW_NODE — a [, <% or @@name left open. Add ], %> or name@@.
  • E_UNTERMINATED_STRING — a quoted value with no closing quote.
  • E_MISMATCHED_CLOSE — inside a node, a close that pairs with no open (@section … aside@ … section@). Match the opener's name.
  • E_MALFORMED_RECORD — a { … } record that is not key: value pairs, including the removed 0.2 separator.
  • E_MALFORMED_FORM_FIELD — a line that is not key: value inside a form-fill data definition (#weil: followed by field lines and !!).
  • E_MALFORMED_STATEMENT — a statement other than (if @path …) / (each @path as name), including the removed 0.2 comparison word. Write is.
  • E_MALFORMED_HEADER — a header entry that is not a name or literal name (#x(a, b c)).
  • E_RESERVED_PARAM — a header parameter named body, which is reserved for ::body::.
  • E_RESERVED_FIELD — a record field named index, count or last, reserved for loop positions.
  • E_CONDITIONAL_DEFINITION — a definition inside (if …) or (each …). Put the condition inside the definition.
  • E_BODY_WITHOUT_SLOT — a closed use of a definition that has no ::body:: (@sig With thanks. sig@). Drop the close, or add ::body:: to the definition.
  • E_PIPE_SYNTAX_REMOVED — a 0.2 pipe parameter or capture list.
  • E_REMOVED_SYNTAX — a 0.2 record-argument call.

For the two removed-syntax codes, run wit migrate; see Syntax.

Runtime codes — RuntimeError

Thrown during resolve, expand or the load pass:

  • E_UNRESOLVED_REFERENCE — resolve: @name names no definition, data, or core node. Define it, or fix the name.
  • E_CIRCULAR_REFERENCE — resolve: reference files form a cycle. Break the cycle.
  • E_MISSING_REFERENCE_FILE — resolve: a reference directive but no rootPath, or the file is missing. Pass rootPath, or handle it with onMissingReference.
  • E_DUPLICATE_DEFINITION — resolve: two non-additive #name definitions. Rename one, or make it a +#name entry.
  • E_PARTIAL_SHAPE_MISMATCH — resolve: +#name entries disagree with each other or the base on shape or parameters.
  • E_POSITIONAL_WITHOUT_HEADER — expand: @c(1952) for a definition with no header. Pass by name, or declare #c(year).
  • E_TOO_MANY_ARGUMENTS — expand: more positional values than header parameters — often a value with a comma. Pass it by name.
  • E_UNKNOWN_PARAM — expand: a leading key: the definition doesn't declare.
  • E_MISSING_PARAM — expand: a use with parameters omits a declared one.
  • E_REMOVED_SYNTAX — expand: a parameter written without its colon, the removed 0.2 form. Write year: 1952.
  • E_AMBIGUOUS_RECORD_KEY — expand: two keys of one record match the same loose key (years at post and years_at_post). Rename one.
  • E_NOT_ITERABLE — expand: (each) targets a non-collection. Point it at a collection.
  • E_EXPANSION_DEPTH_LIMIT — expand: a recursive definition past depth 256. Remove the recursion.
  • E_SCRIPT_ERROR — expand: a <% %> block threw, or @scriptCall named an unknown function. Fix the script.
  • E_LOAD_FAILED — load: a @load alias's loader threw or the dict had no entry. Supply the data or fix the loader.
  • E_MISSING_FIELD, E_TYPE_MISMATCH — declared in RuntimeErrorCode but not thrown today; a missing field renders as a visible wit-unresolved span instead.

How the CLI surfaces them

wit build formats both families identically through formatStageError:

report.wit:12:5: E_UNRESOLVED_REFERENCE: Unresolved reference @author

That is file:line:col: CODE: message — the same shape the embed helper produces.

See also

Parsing → the AST · Resolve & expand · External data · Scripting · CLI reference.