Diagnostics

Every message FantASM prints carries a level, a code and a position.

Anatomy of a Diagnostic

Error [E1003]: undefined symbol `nowhere_at_all`
src/main.asm:12:6
  jp nowhere_at_all
     ^
  • Error is the level.
  • [E1003] is the level’s letter and the code. The letter matters — see Levels.
  • src/main.asm:12:6 is file, line, column.
  • The source line is quoted with a caret under the column, so you do not have to count.

Some diagnostics add more:

help: `nowhere_at_all` is defined outside this module. Use `@nowhere_at_all`

A hint says what to do about it. A note on a second location points at the other half of the problem — where a label was first defined, say, when you have defined it twice.

⚠ A diagnostic without a file:line is about the project file, not your source. The fault is in how fantasm.toml’s tables relate rather than at a point in any text, so there is no line to point at.

Levels

ShownMeaning
ErrorThe build failed. Nothing is written.
Fatal ErrorThe build failed and could not continue far enough to look for more problems.
WarningAssembled, but something is probably wrong.
InfoProgress and detail, shown with -v.
MessageYour own message directive.

The same code number can carry different levels. 1012 is a warning when a value is truncated to 16 bits and an error when the same value cannot be used at all. The level is decided where the diagnostic is raised, which is why the letter is printed and not just the number.

Renumbered Codes

One number means one thing, and a code stands for one fault rather than a family. Two numbers each named two unrelated diagnostics and were told apart only by the level letter, so looking one up found whichever entry came first; four others covered several faults at once, so a [lint] entry or a search of a build log picked out a family rather than the fault meant.

WasIs now
10491082The address error moved; the unused-label warning kept the number.
10601083The NEX entry-point warning moved; the reserved-word error kept the number.
10201129, 1130, 1134, 1135A bad option name, a bad option value and an unknown output format.
1008, 10051136, 1137What a device does not support.
10581005, 1138, 1139, 1140, 1141, 1142Five faults and a test-failure count.

Unused-Label Sweep

Syntax: fantasm build <source> -u

-u turns on that one sweep and nothing else. Every other warning is shown whether or not you pass it, and --no-find-unused turns off only the sweep. find_unused under [assembler] is the same setting in fantasm.toml.

fantasm build src/main.asm -u
[assembler]
find_unused = true

It was -W/--enable-warnings/--no-warnings and warnings until 2.0. Those still work, saying what replaced them once (W1103), and are withdrawn in 2.1.

W1049 unused label does not fire for a label that is KEEP-pinned, GLOBAL-exported, discarded by --gc-modules, or run into by the code above it — in none of those cases is there anything to act on.

Nor for any part of a STRUCT instance something touches. An instance is one object’s layout, so a reference to a member marks the instance and vice versa: ld hl,inst and then indexing through (hl) uses every field without naming one. Deleting a member to answer a warning would move the fields after it, so there is no change to make. An instance nothing touches at all is still reported.

Common Codes

The elaboration below is present where the message alone leaves something unanswered. Every code is in Code Reference.

E1003 undefined symbol …

A typo, a missing INCLUDE, or a name you expected to reach out of a MODULE. Constants do not fall back to global scope from inside a module — use @NAME.

E1004 file not found: …

Check include_dirs. A missing file that is another target’s output is E1078 instead, which says so — see Building Several Images.

E1005 syntax error: …

The line stopped making sense. Where it can say more it adds it after the colon; a bare syntax error means there was nothing useful to name.

E1008 invalid instruction: …

A mnemonic that does not exist in the form you wrote it, or an operand the instruction cannot take.

E1013 … is already defined

The note points at the first definition.

E1016 Z80N instructions are not enabled

Set device = "zxnext", or z80n = true for a Z80N program on another machine. The hint says the same in directive form.

E1020 unknown assembler option …

The name after !opt. A value that option will not take is E1134, and an output format this build does not write is E1135; both name what is actually wrong rather than an option that was fine.

E1036 code size limit exceeded

max_code_size limits how much code there is, not the address it reaches: a program ORGed at $8000 emitting 2 KB has used 2 KB of the budget. zx16 additionally refuses anything above $8000. The hint says which of the two limits was reached.

E1058 General error: …

Nothing in a source file raises it. It stood for a --test run’s failure count, an empty test body, a body with nowhere to go, a !rhai block missing its brace and two fantasm.toml target faults; those are E1138, E1139, E1140, E1005, E1141 and E1142.

E1060 … is a reserved word and cannot be a macro name

E1061 … is a reserved word and cannot be a macro parameter name

A macro’s name and its parameters cannot be words the tokeniser has already claimed — see Reserved Words. E1063 is the neighbouring case of a missing or malformed MODULE or !library name.

E1075 … is a string and cannot be used as a number

__NAME__ and friends carry text. Example: db __NAME__ assembles it, and ld a, __NAME__ is this.

W1068 code at … is in ROM on …

W1069 code at … assembled before the first ORG

Both usually mean a code-bearing INCLUDE sits above your ORG. Anything emitted before an origin lands at $0000.

E1200 Rhai function … failed: …

A !rhai block failed to compile, or the engine ran into a fault. The position points inside the script, at the line you wrote rather than at the !rhai that opened it. What a script says on purpose — ctx.warn, ctx.error — is 1080 instead, in the script’s own words.

Reserved Words

A macro’s name and its parameters must be words the tokeniser has not already claimed. Every word below produces a keyword token instead, so using one there raises E1060 or E1061.

Position decides everywhere else, and most slots take these words happily. A label may be named after any of them, and so may a STRUCT member, an ENUM member or type, a MODULE and a !library: org: is legal, KEEP org pins it, hex equ 9 defines a constant called hex, and Device db is a struct member. A register or condition name still cannot be a constant — a equ 5 is E1005.

assert and debug are in this table like any other directive, and like any other they can still name a label, a STRUCT member and the rest: DEBUG equ 1 with ld b,DEBUG and IFDEF DEBUG all work.

FamilyWords
Directivesorg include binary incbin message db defb byte dw defw word ds block rs section align dh hex opt macro end endm dz if ifdef ifndef else endif global extern enum ende struct ends nex bank page slot sna device target format module endmodule library interface endinterface keep test endtest init_reg init_mem init_cycle_limit assert assert_reg assert_mem assert_cycles assert_checksum debug watch rhai rep endr virtual endvirtual
Opcodesevery Z80 and Z80N mnemonic — ld, nop, jr, mul, …
Registersa b c d e h l i r bc de hl sp ix iy af ixh ixl iyh iyl
Conditionsnz z nc c po pe p m
Operatorsequ
Optionsverbose cspect z80n maxcodesize case_insensitive device target format
Booleanson off true false yes no

Matching is case-insensitive, so Slot and SLOT are reserved too.

E1062 is withdrawn. It refused a module or library named after a reserved word, which is now allowed. device joined this table in 2.0 and costs a struct nothing, a member being read only as Type.member. target is here only while !target is still accepted, and leaves in 2.1.

⚠ This is the first thing to check when a name behaves strangely. A module called A or a macro parameter called c is a register name, and the diagnostic that results rarely mentions registers. It costs nothing to rule out and saves a long search when it is the cause.

Code Reference

The message text is what FantASM prints; … stands for a name, file or value it fills in.

CodeMessage
1001address overflow: PC past $FFFF
1002invalid character in label …
1003undefined symbol …
1004file not found: …
1005syntax error: …
1006invalid constant definition
1007invalid register pair
1008invalid instruction: …
1009value … out of range
1010address $… truncated to $…
1011value … truncated to 8 bits ($…)
1012value … truncated to 16 bits ($…)
1013… is already defined
1014unexpected end of line
1015invalid condition …
1016Z80N instructions are not enabled
1017unmatched )
1018unclosed (
1019CSpect pseudo-ops are not enabled
1020unknown assembler option …
1021invalid expression
1022invalid hex string …
1023bit number … out of range 0..7
1024circular include: …
1025extra characters at end of line: …
1026ENDM without MACRO
1027ENDIF without IF
1028ELSE without IF
1029expected a macro name, found …
1030expected ,
1031expected a parameter name, found …
1032nested MACRO definition
1033macro … takes … parameters, but … were given
1035macro … is already defined
1036code size limit exceeded
1037cannot determine the size of …
1038non-ASCII character in string…
1039expected an 8-bit register
1040expected a name after ENUM
1041ENDE without ENUM
1042invalid ENUM member name …
1043ENUM step cannot be zero
1044expected a name after STRUCT
1045ENDS without STRUCT
1046invalid STRUCT member name …
1047invalid size for STRUCT member …
1048STRUCT … is already defined
1049unused label … (a warning, from -u)
1050unknown directive …
1052unknown !sna option …
1053unknown !nex option …
1054expected a !nex option, found …
1055expected a !sna option, found …
1056Your own message directive
1057shebang line ignored
1058General error: … — nothing in a source file raises it; see 1005 and 1138–1142
1059address $… in bank … has already been written
1060… is a reserved word and cannot be a macro name
1061… is a reserved word and cannot be a macro parameter name
1063expected a name after MODULE, found …
1064ENDMODULE without MODULE
1065unterminated MODULE …
1066expected a label after KEEP, found …
1067undefined symbol … in KEEP
1068code at … is in ROM on …
1069code at … assembled before the first ORG
1070expected a name after GLOBAL, found …
1071undefined symbol … in GLOBAL
1072unknown escape sequence \…
1073size computed from $ at …, but the line was placed at …
1074unterminated …
1075… is a string and cannot be used as a number
1076invalid digit separator ' after …
1077circular dependency between targets: …
1078… not found: it is written by target …, which … does not depend on
1079ifdef cannot test macro …
1080What a script said through ctx.warn or ctx.error, in its own words
1081What a script printed — twenty lines a block, then a count of the rest
1082invalid … (was 1049, which the unused-label warning kept)
1083NEX entry point … contains no code (was 1060, which the reserved-word error kept)
1084… is only referenced from a !test block and was removed by --gc-modules
1085output is not contiguous: $…..$… spans … bytes but … were emitted
1086… evaluated to … before its MODULE body was placed, and is now …
1087IF condition evaluated to … before the MODULE body was placed, and is now …
1088undefined Rhai function …
1089… is a label and cannot be used in !opt
1090Rhai function … in … shadows the definition in …
1091A !test assertion did not hold: what it checked, and what it found
1092… cannot be relocated (relocatable output only)
1093unknown instruction, directive or macro …
1094… at column 0 defines a label, not a macro call
1095!library must be at the top level of its file
1096library … is already declared in …
1097INTERFACE must be at the top level of a library
1098duplicate INTERFACE in library …
1099ENDINTERFACE without INTERFACE
1100INTERFACE of library … lists undefined symbol …
1101… is private to library …
1102--reloc requires a single-segment bin image: …
1103… is deprecated; use … (the old spelling still works, and leaves in 2.1)
1104test … did not halt within … T-states
1105unknown option … for …: expected one of …
1106duplicate option … on …
1107cannot mix positional and name=value arguments on …
1108expected an option name for …: one of …
1109… requires …
1110… and … cannot both be given on …
1111span … is outside physical memory (… bytes)
1112span … runs past the end of … (… bytes)
1113second ELSE for one IF
1114invalid NEX version …: expected V1.2 or V1.3
1115NEX V1.2 was requested, but … requires V1.3
1116macro … exceeds the nesting limit of 64
1117!nex screen is not supported
1118STRUCT … cannot contain itself
1119unknown member type …
1120… is ignored without an SLD file
1121block size … out of range 0..65536
1122… outside a !test block
1123index displacement … out of range -128..127
1124unknown key … in fantasm.toml
1125REP repeats an instruction, and … is not one
1126REP count … out of range 0..65536
1127expected , after the REP count
1128ENDR without REP
1129unknown device …
1130… has 16K banks, not 8K pages
1131unknown diagnostic code … in [lint]
1132[lint] … is not configurable
1133invalid level … for [lint] …: expected allow, warn or deny
1134invalid value … for option …
1135unknown output format …
1136… is not supported on …
1137bank takes no slot on … (a 16K bank has one window)
1138… tests failed — the count that fails the build, at the first failure
1139test … has an empty body
1140no room for test … above the program
1141unknown target …
1142target … depends on unknown target …
1143!endvirtual without !virtual
1144… is not allowed inside a !virtual block
1145nested !virtual block
1146!virtual cannot be used with --reloc
1147invalid IF condition …
1148ALIGN … is not a power of two, rounded up to …
1149output was not written in address order
1150… takes no value
1151… requires a value
1152expected a section name, found …
1153conflicting options on section …: …
1154SECTION is not allowed inside a MODULE
1155ORG is not allowed inside a SECTION
1156EXTERN requires object output
1157expected a symbol name after EXTERN, found …
1158… is not allowed inside a SECTION
1159… cannot be used with object output
1160cannot determine the page of …
1161labels file … is stale: … has been rebuilt since it was written
1162labels file … names …, which cannot be read
1163… is not allowed in an object file
1164!test is not allowed in an object file
1165undefined reference to … in …
1166multiple definition of … in … and …
1167… and … were assembled for different devices
1168cannot read object file …: …
1169section … uses placement rule …, which is not supported
1170no space for section … (… bytes)
1171section … extends … bytes past $FFFF
1172section … is … bytes larger than a page
1173section … crosses from page … into page … without straddle
1174section … at $… overlaps a section at $…
1175section … at $… is in ROM
1176relocation … against … out of range: …
1177cannot resolve relocation … against …: …
1179… in page … has no window and cannot be called from page …
1200Rhai function … failed: …

← Documentation