Error codes¶
Assembler diagnostics carry a stable error code so you can search docs
by code, suppress individual rules in tooling, and correlate output
across CLI runs. Every assembler diagnostic carries one; the test suite
fails if a new error is raised without a code or a code is missing from
the catalog below. a816 explain E0317 prints a code's entry.
Anatomy¶
error[E0200]: `my_routime` is not defined in the current scope
--> dym.s:4:11
|
3 | rts
4 | jsr.l my_routime
| ^^^^^^^^^^
5 |
= hint: did you mean `my_routine`?
error[CODE]: severity + stable identifier.--> file:line:column: the failure location.- Source block with
±1context lines and a caret pointing at the offending span. - Optional
= hint:/= note:lines with fix suggestions.
When multiple errors come out of one parse pass they are rendered as separate blocks separated by a blank line.
Categories¶
E0001..E0099: scanner / lexing.E0100..E0199: parser.E0200..E0299: symbol resolution.E0300..E0399: codegen.E0400..E0499: linker / object files.E0500..E0599: I/O / config.W0001..: warnings. The build still succeeds.
Code catalog¶
Scanner¶
E0001invalid input character: the scanner met a character it doesn't know how to start a token with.E0002unterminated string literal: close the string with the matching quote character.E0003unknown directive keyword:.directivenot in the supported set; see directives.md.E0004unterminated block comment: a/*with no closing*/. The caret sits on the opening/*.
Parser¶
E0100unexpected token: generic structural failure.E0101missing expected token: the parser knew what it wanted next but found something else.E0102invalid expression: the expression couldn't be parsed at the given position.E0103duplicate struct field: each.structfield name must be unique within the block.E0104typed-cast bind requires:=: usename := expr as Tinstead of=.E0105field access requires typed cast:(expr).fieldonly works on a typed cast:(expr as Type).field.E0106unknown directive attribute: the directive doesn't accept the attribute name.E0107pool declares no ranges: every.poolneeds at least onerange LO HI.E0108unknown pool strategy: accepted values:pack,order.E0109include file unreadable: the path resolution failed.E0115opcode needs an operand. The opcode is followed by}or the end of input where its operand should be ({ lda }).E0120struct array count must be a positive integer (byte[0] x); the caret sits on the count.E0121bit-field struct fields cannot be arrays (u4[2] x).E0122field initialized twice in one.istruct(or nested{ }) initializer; the caret sits on the second entry.E0123string inside a[...]initializer list. A byte array takes the string itself:name = "TEXT".
Symbols¶
E0200symbol not defined: the resolver couldn't find this symbol; the error includes a did-you-mean suggestion when a close match exists in scope.E0201external reference outside object mode.E0202expression failed to evaluate: likely a forward reference the resolver couldn't bind.E0205placement into an undeclared pool..alloc,.reserve,.relocateand.reclaimname a pool that no.pooldeclared before them. The caret sits on the pool name.E0206.reserve NAME as TYPE in POOLnames a struct type that isn't declared. The caret sits on the type name.E0207macro not defined. The hint suggests the closest defined macro name.E0208macro called with the wrong number of arguments.E0209symbol names a block, not a value: a block argument (m({ ... })) used where an expression is expected.E0210:=references a symbol not yet defined.:=evaluates its right-hand side immediately (typed binds need the address up front); use=for a forward reference.E0211symbol names a value, not a block:{{NAME}}inlines a block argument, andNAMEholds an expression instead.E0212.importnames a module found on no module path (-I,module-pathsina816.toml, or the bundled@stdmodules).E0213.textwith no.tablein scope: declare the character table before encoding text with it.
Codegen¶
E0300node failed during emission: generic codegen failure.E0301unknown struct field type:.structreferences an identifier that isn't a primitive or a previously-declared struct.E0302struct field self-reference: a struct cannot embed itself.E0303struct redefined.E0304typed bind references unknown struct type.E0305typed bind or cast base must evaluate to an address ((expr as T)with a stringexpr).E0306operand size mismatch.E0307addressing mode not supported by opcode.E0308conflicting.mapdeclaration. Two modules (or a module and one it.imports, or a module and thea816.tomlbus map) declare the same identifier with different ranges, mask, writable flag or mirror.E0309byte immediate does not fit in 8 bits: an explicit.bimmediate whose value exceeds0xFF.E0310code emitted outside any placement. Undera816 build, a module (entrypoint included) emitted bytes before any*=and outside every.alloc. Wrap them in.allocor set*=first.E0311.importinside a placement context..importmust sit in the file prelude, before the first*=and outside any.allocbody. An.importinside an.ifis rejected too: the build reads imports before any condition is evaluated, so the module was linked whatever the condition. Import it unconditionally and put the.ifinside the module.E0312division or modulo by zero. The right-hand side of a/or%evaluated to 0; the caret points at the operator. In a relocation resolved at link time the linker reportscannot evaluate expressionwith reasondivision by zero.E0313an unsized operand names a symbol resolved at link (jmp targetwithtargetfrom another module): its value is unknown at compile time, so the form can't be chosen. Write the size; the hint lists the forms the opcode has (jmp.win the same bank,jmp.lacross). Register-sized immediates and single-form opcodes (pea,rep) need none.E0315branch target out of range: the displacement does not fit the branch's signed 8-bit (bra,bne, ...) or 16-bit (brl) offset. The caret sits on the target.E0316branch target has no ROM address. Relative branches are computed in ROM space; a RAM target cannot be reached.E0317address in a bank no.mapregion covers (and the configured ROM type doesn't back). The hint lists the mapped banks.E0318alloc does not fit in its pool. Says whether the alloc is larger than any range, the pool is fragmented or out of room, with a matching hint; the caret sits on the.allocname.E0319operator applied to a string and a number.E0320~operand wider than 32 bits.E0321sizeof(...)/countof(...)names nothing visible here it can size (a struct, struct field, reservation or named alloc),sizeofnames a bit field, orcountofnames a field that is not an array. The caret sits on the argument; the hint suggests a close name or the.importthat would make it visible.E0330.istructnames a struct type that is not declared (or imported) yet; the caret sits on the type.E0331.istructinitializer names a field the struct does not have; the hint lists the struct's fields.E0332initializer value does not fit the field: scalars take an expression, byte arrays a string or[...], other arrays[...], struct fields{ ... }.E0333string or list initializer longer than its array field.E0334non-ASCII character in a string initializer.E0335initialized bit-field run wider than 32 bits.E0336across_bankalloc body holds something other than data (code or a label); see Freespace pools.E0337an alloc body emitted a different number of bytes than the slot it reserved. Measuring and emitting disagree: an a816 bug, please report it with the source.E0338invalid.pooldeclaration: a range or fill that is not a constant integer, a fill outside0x00..0xFF, or ranges that overlap or run backwards.E0339a pool declared again with a different fill, strategy,bssflag orcontextslist, or a second declaration with new ranges in the same file. Two modules may each contribute ranges to one pool; within a file,.reclaimadds a range.E0340invalidalignon an.alloc: not a power of two, or a pinned address off its boundary.E0341a placement directive (*=,.alloc,.relocate) nested in an.allocbody.E0342a range given back to a pool (.reclaim, or the old range of a.relocate) overlaps a range the pool already has, or runs backwards.E0343a size that must be positive is not:.alloc at ADDR size NwithN <= 0, or a negative.res N.E0344an.allocin absspool emits bytes; reserve space with.resor.reserveinstead.E0345a.labeladdress does not evaluate to an integer.E0346a barejsr/jmpnames a target in another bank. A bare operand takes the absolute form in the caller's own bank (a 16-bit value is always an address there); into another bank, writejsl/jml(ajslcallee returns withrtl), orjsr.w/jmp.wwhen that bank mirrors this one.E0347a reference to a path-derived.incbinname that two blobs in the module bind: the same file included twice, or two paths that collapse to one name (f.binandf_bin). It would read whichever came first. Label each blob and use the labels (seeW0001).E0348a.patchgives some fields of a bit-field byte but not all: a816 never sees the ROM's byte, so give every field that shares it.
Linker¶
E0400duplicate global symbol. Names each definition: the defining module (its source, or its object for a constant-only module) and value.E0401unresolved external symbol.E0402relocation out of range.E0403relocation expression failed.E0404alloc does not fit in its pool at link time (the pool is shared across modules, so the allocator only runs once every.ois in). Same message and hint asE0318, plus the pool and, when the body emitted code, thefile:lineof its first instruction.E0405an alloc request names a pool that no linked object declares.E0406reservations from two differentbsspools share memory. Lists every clash with both reservations, their spans and theirfile:line. Memory used in turns goes in one pool'scontexts(see Freespace pools).E0407a.assertis false once every address is final. Lists each failed assert with its message, expression andfile:line.E0408two placed blocks would write the same ROM bytes. Names both blocks (an alloc and its pool, or an anonymous block by address) with their sizes, addresses andfile:line, and the bytes they share. Pools place around every pin inside their ranges, so this is two pins on the same bytes, or two pools whose ranges hand out the same bytes.--overlap-mode warnreports it and builds anyway.
I/O / config¶
E0500file not found.E0501invalid project config:a816.tomlis not valid TOML (a repeated[map.N]table is one way to get there).E0502.include_ipsfile is not an IPS patch (noPATCHheader). An unreadable.include_ipspath reportsE0500.E0503[experimental]ina816.tomlis not a table, or one of its flags is nottrue/false.E0504a816.tomlstill setsmapper, which was removed: the message names theboardto write instead.E0505malformed[map.N]entry: not a table, an unknown key, a missingaddress, or two keys spelling the same number ([map.1]and[map.0x1]).E0506a[map.N]value is invalid:N,maskandbaseare integers,addressis aBANKS:WINDOWhex string ("00-3f,80-bf:8000-ffff"),writablea boolean; orrom_sizeis missing (with a read-only region), not an integer, or not positive.E0509boardnames no board inboards.bml; the message suggests close names.E0510[defines]is not a table, a key is not a symbol name, or a default is not an integer or a string.E0511not a valid BPS patch: noBPS1header, truncated, an action reading outside the ROM or the bytes written so far, or a CRC32 that does not match (the patch's own, or the patched ROM's).E0512the source ROM is not the one the BPS patch expects: its size or CRC32 differs. A ROM 512 bytes too long carries a copier header; strip it first.E0513-f bpswithout a[bps]table ina816.toml, or a malformed one:source_sizeandsource_crc32are non-negative integers,[bps.metadata]a flat table of attribute names to strings.E0514a${NAME}in a[bps.metadata]value names no define: pass-D NAME=...or declare it under[defines].E0515--copier-headerwith-f bps: a BPS patch records the CRC32 of a headerless ROM, so a header offset cannot apply.E0516[lint]select/ignore, ora816 check --select/--ignore, names a code no lint rule starts with:a816 explain CODElists a rule, and the codes match by prefix (Nis every naming rule).E0517not a valid IPS patch: it does not start withPATCH, or a record runs past the end beforeEOF.E0518sealing against a base ROM that carries a 512-byte copier header: the checksum and the patch offsets are for a headerless ROM. Strip the header first.E0519a816 ips sealoutside a project that declares its cartridge: the checksum's place and the ROM size come from thea816.tomlboardor[map.N]androm_size.
Warnings¶
W0001a reference to a name.incbinderived from its file path:.incbin "assets/vwf.bin"bindsassets_vwf_binandassets_vwf_bin__size, which change when the file moves. Name the blob instead: alone in.alloc vwf_font { ... }it isvwf_font, and its sizesizeof(vwf_font);a816 fixrewrites those references. Where the blob shares its block, put a label before it. The path names go in 1.2. Reported by the build (by the linker for a module that names the blob without importing its module, and again when a module comes from the build cache) and bya816 check.W0002an.ifnames something the project defines nowhere (in no.s/.ifile under itsa816.toml). An undefined name reads as false, which is how.if DEBUGworks without-D DEBUG, so a deleted or misspelt flag silently drops what it gated. Declare a name that only comes from-Dunder[defines]ina816.toml. Reported bya816 check.
LSP integration¶
The a816-lsp-server publishes diagnostics with the same code and
appends the hint to the message. Editors that recognise the code
field (VS Code, Helix, Neovim with vim.diagnostic) render it as the
familiar inline chip.
Suppressing noise¶
There is no global suppression knob for E* errors: they signal real
failures, not style issues. Style-style suppression lives on the
fluff side (; noqa: <RULE> for DOC* / S* / N*); see
fluff.md.