moxzi
Docs / Reference / Error and diagnostic codes

Error and diagnostic codesalpha

What does this error mean and what do I do about it?

A moxzi diagnostic is an M#### code attached to a source region, a severity and a category, rendered the way moc renders one so editors and habits carry over. The code registry (mops/mo-langutils/src/ErrorCodes.mo, a port of moc's error_codes.ml) lists about 204 error codes and 43 warning codes; 65 are actually emitted — the rest are declared for parity and never raised.

How a diagnostic is printed#

/src/main.mo:4.10-4.19: type error [M0030], type field does not exist in type
  note: ...
PartWhere it comes from
file:l.c-l.cthe message's region
typethe category word; warnings drop it
error / warning / infoDiag.Severity (mops/mo-langutils/src/Diag.mo:36)
[M0030]the code; omitted when empty, and always omitted for info
notesrendered one per line, prefixed note: — usually the inferred type

A build fails when any message has severity #Error (Diag_hasErrors, Diag.mo:253). The CLI's renderer is render_diag in moxzi/src/compile.rs:293; the JSON form emits message, code, level, spans, notes.

The codes you will actually hit#

CodeMeaningWhat to do
M0220this actor or actor class should be declared persistentadd persistent, or build with --default-persistent-actors
M0096expression of type T cannot produce expected type Uthe generic check-mode mismatch; read the note for the inferred type
M0057unbound variabletypo, missing import, or a name not in scope
M0026unbound variable in a paththe module qualifier does not resolve
M0029unbound typethe type name does not resolve
M0028 / M0030field / type field does not existwrong qualifier or wrong package version
M0020unresolved importa missing mo: package or a wrong relative path
M0006import cyclebreak the cycle; moxzi names the path
M0016cannot use x before y has been definedreorder, or wrap in a function
M0031 / M0032shared function has a non-shared parameter / return typeonly shared types cross a message boundary
M0072field does not exist in {…}the record literal is missing it
M0073expected mutable assignment targetdeclare the binding var
M0077a shared function is only allowed as a public field of an actormove it into the actor
M0082expected iterable type.vals() / .keys()
M0088expected async typeyou are awaiting something that is not a future
M0037 / M0038misplaced await/async; try enclosing in an async function/expression
M0064misplaced !there is no enclosing do ? { }
M0097expected function typeyou are calling a non-function
M0102 / M0103cannot infer the type of a wildcard / variableadd an annotation
M0112–M0117pattern cannot consume the expected typetuple, option, object, variant, operator and general forms
M0119show is not defined for this typedebug_show needs a showable type
M0124 / M0125public actor field has a non-shared function type / is not a manifest function
M0141an actor or actor class must be the only non-imported declarationmove declarations into the actor body
M0175to_candid argument must have a shared type
M0184 / M0261cannot infer the type of this or-/and-patternannotate it
M0189 / M0260different bindings in pattern alternatives / bound in both and-pattern legs
M0225a mixin cannot be an entry pointinclude it in an actor
M0233cannot resolve implicit argumentpass it explicitly
M0238break/continue outside a loop

Emission sites are almost entirely in mops/mo-frontend/src/Typing.mo, with Static.mo, Definedness.mo, Resolve.mo and bin/compiler-canister/Main.mo supplying the rest.

Codes with moxzi-specific wording#

Codemoxzi's wordingNote
M0069non-toplevel actor; an actor can only be declared at the toplevel of a programmoxzi emits M0069 alone where moc also reports M0037 and M0038 — a deliberate divergence, gated by scripts/nontoplevel_actor_matrix.sh
M0057 (prim gate)unbound variable prim / help: did you mean variable Prim?an authorization gate, not a type error: prim is only available with MOC_UNLOCK_PRIM
M0096 (arity form)call supplies N arguments but the function expects M (with K implicit param(s)); implicit insertion cannot reconcile the differencea second, more specific M0096 at Main.mo:2710
M0250a stable variable under --enhanced-migration carries an initializerdelete it; the migration chain supplies the value
M0267a stable field the migration chain cannot explain, measured against --stable-baseline — the message names the boundary it was measured at (initial actor or upgrade resuming after migration m2``)write a migration that produces the field, or correct the baseline
M0169 / M0170 / M0216the upgrade-compatibility verdicts (dropped variable / incompatible type / silent data loss), from moxzi stable-compatible and the baseline checksame meanings as moc
M9000unimplemented: <what>moxzi-only. Not a program error — a compiler feature that is not ported. Report it

Warnings#

Severity is a property of the message, not of the code. Warnings print on successful builds, before the provenance line. Four are emitted today:

CodeMeaning
M0089redundant ignore on an operand already of type ()
M0254a stable field the migration chain does not produce (without --stable-baseline; with one it becomes error M0267)
M0265mixin capability mismatch
M0266a float literal with more precision than Float can represent, naming what it rounds to

The other registered warning codes — including M0194 (unused identifier) and M0145/M0146 (pattern coverage) — are inert, which is a real stderr difference against moc (called out in scripts/shared_type_matrix.sh).

Lint levels exist (mops/mo-sys/src/Flags.mo:47, #Allow/#Warn/#Error). Four codes are suppressed by default: M0223, M0235, M0236, M0237, matching moc's defaults.

M0000 is overloaded#

moxzi uses M0000 for several things moc splits up: parse errors (moc uses M0001), filesystem and import failures, prelude and desugar failures, job authorization refusals, and IR subtype violations (Ill-typed intermediate code: subtype violation). If you are matching on diagnostics programmatically, match the text as well as the code — the corpus harness does exactly that.

Runtime errors#

Traps and rejects, not compile-time diagnostics. Formatted in one place, ic_reject_message at moxzi/runtime/src/machine.rs:328, matching the IC's first line.

FormWhen
IC0503: Error from Canister <id>: Canister called ic0.trap with message: '<t>'.an explicit ic0.trap — most Motoko traps
IC0502: Error from Canister <id>: Canister trapped: <text>.a recognised wasm trap; currently only stack overflow

Reject codes follow the IC's numbering (moxzi/runtime/src/sys.rs:28): 1 SYS_FATAL, 2 SYS_TRANSIENT, 3 DESTINATION_INVALID, 4 CANISTER_REJECT, 5 CANISTER_ERROR, 6 SYS_UNKNOWN.

Two messages you will meet that are not codes at all:

MessageSource
self-calls nested more than 512 deep (a runaway async chain?)the shared call-depth cap; the same in the browser and natively
Canister exceeded the limit of 40000000000 instructions for single message executionthe replica, on-chain only. moxzid kills the message at its own --instruction-limit instead

Things this page cannot tell you#

Code-to-explanation prose exists for only a handful of codes (M0003, M0037 and a few others carry a long-form .md flag in the registry). There is no per-code explainer command. If a diagnostic is unclear, that is a bug worth filing — see Reporting a bug.

Next#

On this pageHow a diagnostic is printedThe codes you will actually hitCodes with moxzi-specific wordingWarningsM0000 is overloadedRuntime errorsThings this page cannot tell youNext