Diagnostics
Every message FantASM prints carries a level, a code and a position.
Anatomy of a Diagnostic
Error [E1003]: Undefined label or constant: `nowhere_at_all`
src/main.asm:12:6
jp nowhere_at_all
^Erroris the level.[E1003]is the level’s letter and the code. The letter matters — see below.src/main.asm:12:6is 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:
Hint: use @NAME to reach a constant outside this moduleA 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
| Shown | Meaning |
|---|---|
Error | The build failed. Nothing is written. |
Fatal Error | The build failed and could not continue far enough to look for more problems. |
Warning | Assembled, but something is probably wrong. |
Info | Progress and detail, shown with -v. |
Message | Your 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.
One number, one meaning. 1049 and 1060 each named two unrelated diagnostics, told apart only by the level letter — so looking one up found whichever entry came first. The address error moved to 1082 and the NEX entry-point warning to 1083; the two numbers now mean what most people already thought they meant.
A code that stood for several faults now stands for one. 1020 covered a bad option name, a bad option value and an unknown output format; 1058 covered five things at once. Each has its own code, so a [lint] entry or a search of a build log picks out the fault you mean rather than its family. The splits are 1020 → 1129, 1130, 1134, 1135; 1008 and 1005 → 1136, 1137; and 1058 → 1005, 1138, 1139, 1140, 1141, 1142.
The Unused-Label Sweep
-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.
fantasm build src/main.asm -uor in fantasm.toml:
[assembler]
find_unused = trueIt 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
E1003 Undefined label or constant. 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. If the missing file is another target’s output, you get E1078 instead, which is more useful — see Building Several Images.
E1005 Syntax error and E1008 Invalid instruction. Usually a mnemonic that does not exist in the form you wrote it, or an operand the instruction cannot take. Where either can say more it adds it after a colon; a bare Syntax error means the line stopped making sense and there was nothing useful to name.
E1013 Attempt to redefine label or constant. The note points at the first definition.
E1016 Z80n extended instructions are not enabled. Set device = "zxnext", or z80n = true for a Z80N program on another machine.
E1020 … is not an 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.
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.
E1036 Maximum code size 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.
W1068 Code emitted in ROM and W1069 Code assembled before any ORG. Both usually mean a code-bearing INCLUDE sits above your ORG. Anything emitted before an origin lands at $0000.
E1060, E1061 Reserved word. A macro’s name and a macro’s parameters cannot be words the tokeniser has already claimed — see below. E1063 is the neighbouring case of a missing or malformed MODULE or !library name.
E1075 This is a string, which has no numeric value. __NAME__ and friends carry text. db __NAME__ assembles it; ld a, __NAME__ cannot.
E1200 Rhai error. 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.
⚠ E1062 is withdrawn. It refused a module or library named after a reserved word, which is now allowed.
⚠ 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.
| Family | Words |
|---|---|
| Directives | org include binary incbin message db defb byte dw defw word ds block dh hex opt macro end endm dz if ifdef ifndef else endif global 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 rhai rep endr |
| Opcodes | every Z80 and Z80N mnemonic — ld, nop, jr, mul, … |
| Registers | a b c d e h l i r bc de hl sp ix iy af ixh ixl iyh iyl |
| Conditions | nz z nc c po pe p m |
| Operators | equ |
| Options | verbose cspect z80n maxcodesize case_insensitive device target format |
| Booleans | on off true false yes no |
Matching is case-insensitive, so Slot and SLOT are reserved too.
⚠ device joined this table in 2.0, and costs a struct nothing: a member may be named after any reserved word, 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.
The Full Reference
The message text is what FantASM prints; … stands for a name, file or value it fills in.
| Code | Message |
|---|---|
1001 | Address overflow, PC > 65535 |
1002 | Invalid character in label |
1003 | Undefined label or constant: … |
1004 | File not found: … |
1005 | Syntax error: … |
1006 | Bad constant definition |
1007 | Invalid register pair |
1008 | Invalid instruction: … |
1009 | Integer out of range |
1010 | Address is out of range, the value has been truncated |
1011 | Integer has been truncated to 8 bits |
1012 | Integer has been truncated to 16 bits |
1013 | Attempt to redefine label or constant |
1014 | Unexpected end of line |
1015 | Invalid condition |
1016 | Z80n extended instructions are not enabled |
1017 | Unexpected closing parentheses |
1018 | Unclosed parentheses |
1019 | CSpect pseudo ops are not enabled |
1020 | … is not an assembler option |
1021 | Invalid number or expression |
1022 | Invalid Hexadecimal string |
1023 | Bit number is out of range and will be truncated |
1024 | circular INCLUDE: … |
1025 | Discarded extra characters at end of line |
1026 | Encountered END without MACRO directive |
1027 | ENDIF without IF |
1028 | ELSE without IF |
1029 | Invalid or missing macro name, found … |
1030 | Comma expected |
1031 | Invalid or missing macro parameter name, found … |
1032 | Macros may not be nested |
1033 | Incorrect number of macro parameters |
1035 | Macro already defined |
1036 | Maximum code size exceeded |
1037 | … has no size that can be determined |
1038 | String contains non-ascii characters… |
1039 | Invalid 8-bit register |
1040 | ENUM name expected |
1041 | ENDE without ENUM |
1042 | Enum member name is invalid |
1043 | Enum step value cannot be zero |
1044 | STRUCT name expected |
1045 | ENDS without STRUCT |
1046 | STRUCT member name is invalid |
1047 | STRUCT member size suffix is invalid |
1048 | STRUCT already defined |
1049 | unused label … (a warning, from -u) |
1050 | Invalid directive |
1052 | Unknown SNA command: … |
1053 | Unknown NEX command: … |
1054 | Expected NEX command, found: … |
1055 | Expected SNA command, found: … |
1056 | Your own message directive |
1057 | Shebang detected and ignored: … |
1058 | General error: … — nothing in a source file raises it; see 1005 and 1138–1142 |
1059 | Memory region overlap detected |
1060 | … is a reserved word and cannot be a macro name |
1061 | … is a reserved word and cannot be a macro parameter name |
1063 | Invalid or missing module name, found … |
1064 | ENDMODULE without MODULE |
1065 | MODULE … was never closed with ENDMODULE |
1066 | Invalid or missing label after KEEP, found … |
1067 | KEEP names …, which is not defined |
1068 | Code emitted at … is in ROM and cannot run |
1069 | Code assembled at …, before any ORG set an origin |
1070 | Invalid or missing name after GLOBAL, found … |
1071 | GLOBAL names …, which is not defined |
1072 | Unknown escape \… in a string or character literal |
1073 | A size computed from $ was settled at …, but the line was placed at … |
1074 | … was never closed |
1075 | … is the string “…”, which has no numeric value |
1076 | A digit separator must be _, not ' — found after … |
1077 | Targets depend on each other in a cycle: … |
1078 | … not found. It is the output of target …, which … does not list in depends |
1079 | … is a macro; ifdef and ifndef test constants and cannot see one |
1080 | What a script said through ctx.warn or ctx.error, in its own words |
1081 | What a script printed — twenty lines a block, then a count of the rest |
1082 | Invalid address or bank (was 1049, which the unused-label warning kept) |
1083 | NEX entry point … has no code (was 1060, which the reserved-word error kept) |
1084 | … is referenced only by a !test block and has been discarded by --gc-modules |
1085 | Code between … and … is not contiguous: an ORG skipped a range, or two wrote to one address |
1086 | … was worked out from a MODULE label before its body was placed; corrected, and said |
1087 | if chose its branch from a MODULE label before its body was placed |
1088 | … is not a function in any script loaded above this line |
1089 | An !opt value names an address, which is not settled while options are read |
1090 | Two loaded scripts define …; the later one is the one that will be called |
1091 | A !test assertion did not hold: what it checked, and what it found |
1092 | … names an address in a form relocation cannot patch (relocatable output only) |
1093 | … is not an instruction, a directive or a macro — a label must start at column 0 |
1094 | … is a macro; at column 0 this defines a label rather than expanding it |
1095 | A library is the whole of its file and cannot be declared inside anything |
1096 | Library … is already declared by … — two files claiming one name |
1097 | INTERFACE belongs at the top level of a library |
1098 | Library … already declares an INTERFACE |
1099 | ENDINTERFACE without INTERFACE |
1100 | Library … promises … in its INTERFACE but never defines it |
1101 | … is not in library …’s INTERFACE; @NAME goes round it |
1102 | --reloc needs one image moved by one delta: … |
1103 | … is deprecated; use …. The old spelling still works, and leaves in 2.1 |
1104 | … was still running after … T-states — no halt, or longer than the ceiling allows |
1105 | … is not an option of …; the ones it takes are named |
1106 | … is given twice on one … |
1107 | … takes positional arguments or name=value ones, not both on a line |
1108 | … expected an option name — a trailing comma, or a value written without its name |
1109 | … needs …: a span must say where it starts, how far it runs, and what it holds |
1110 | … takes … or …, not both — two starts, or two sources for the bytes |
1111 | The span … runs past the end of memory, which is … bytes. A phys span is refused, not wrapped |
1112 | … is … bytes, and the span … runs past the end of it |
1113 | A second ELSE for one IF; the first already names the alternative |
1114 | … is not a NEX version; write V1.2 or V1.3 |
1115 | V1.2 was asked for, but this file uses …, which is a V1.3 feature |
1116 | … is nested more than 64 macros deep; a macro that invokes itself never ends |
1117 | !nex screen needs loading-screen data, which is not written |
1118 | … cannot hold a …; a struct’s size would have no end |
1119 | … is not a size or a struct type; a type must be defined above the member |
1120 | … is recorded nowhere without an SLD file; name one with --sld <file> |
1121 | A block of … bytes cannot be reserved; a count runs from 0 to 65536 |
1122 | … belongs between !test and !endtest; outside a block it runs against nothing |
1123 | An index displacement of … does not fit; it runs from -128 to 127 |
1124 | … is not a fantasm.toml key |
1125 | REP repeats an instruction, and … is not one |
1126 | REP cannot assemble … statements; a repetition runs from 0 to 65536 |
1127 | REP takes a count, a comma, then the instruction to repeat |
1128 | ENDR closes a REP block, and none is open |
1129 | … is not a machine this build knows; assembling for the default instead |
1130 | page and slot are the Next’s 8K paging; … pages in 16K banks, so use bank |
1131 | [lint] … names no diagnostic |
1132 | [lint] … is not a diagnostic a project may reconfigure |
1133 | [lint] … = … is not allow, warn or deny |
1134 | … does not take … — the option is fine, the value is not |
1135 | … is not an output format this build writes |
1136 | … is not a directive … has — bank or page on a machine without them |
1137 | bank takes no slot on …; a 16K bank has one window |
1138 | … tests failed — the count that fails the build, at the first failure |
1139 | … has no body to run |
1140 | There is no room to place …: the program fills the address space |
1141 | No target named …. This project declares … |
1142 | … depends on …, which this project does not declare |
1200 | A Rhai script failed to compile, or the engine raised a fault running one |