Diagnostics

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

Reading one

Error [E1003]: Undefined label or constant: `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 below.
  • 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:

Hint: use @NAME to reach a constant outside this module

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.

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.

Asking for more warnings

-W turns on the unused-label sweep and nothing else. Every other warning is shown whether or not you pass it.

fantasm build src/main.asm -W

or in fantasm.toml:

[assembler]
warnings = true

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.

Meeting the common ones

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. Both quote what they found.

E1013 Attempt to redefine label or constant. The note points at the first definition.

E1016 Z80n extended instructions are not enabled. Set target = "zxnext", or z80n = true for a Z80N program on another machine.

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.

E1060E1063 Reserved word. A macro name, macro parameter or module name cannot be a word the tokeniser has already claimed — see below.

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 name, a macro parameter name and a module name must be words the tokeniser has not already claimed. Every word below produces a keyword token instead, so using one raises E1060, E1061 or E1062.

A label may be named after any of these, and a constant after a directive: org: is legal, KEEP org pins it, and hex equ 9 defines a constant called hex. A register or condition name cannot be a constant — a equ 5 is E1005.

FamilyWords
Directivesorg 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 target format module endmodule keep test endtest init_reg init_mem assert_reg assert_mem assert_cycles rhai
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 target format
Booleanson off true false yes no

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

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.

Every code

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

CodeMessage
1001Address overflow, PC > 65535
1002Invalid character in label
1003Undefined label or constant:
1004File not found: …
1005Syntax error…
1006Bad constant definition
1007Invalid register pair
1008Invalid instruction…
1009Integer out of range
1010Address is out of range, the value has been truncated
1011Integer has been truncated to 8 bits
1012Integer has been truncated to 16 bits
1013Attempt to redefine label or constant
1014Unexpected end of line
1015Invalid condition
1016Z80n extended instructions are not enabled
1017Unexpected closing parentheses
1018Unclosed parentheses
1019CSpect pseudo ops are not enabled
1020Invalid assembler option: …
1021Invalid number or expression
1022Invalid Hexadecimal string
1023Bit number is out of range will and will be truncated
1024Source file previously included
1025Discarded extra characters at and of line
1026Encountered END without MACRO directive
1027ENDIF without IF
1028ELSE without IF
1029Invalid or missing macro name, found
1030Comma expected
1031Invalid or missing macro parameter name, found
1032Macros may not be nested
1033Incorrect number of macro parameters
1034Only local labels are permitted inside macros
1035Macro already defined
1036Maximum code size exceeded
1037SizeOf cannot be determined
1038String contains non-ascii characters…
1039Invalid 8-bit register
1040ENUM name expected
1041ENDE without ENUM
1042Enum member name is invalid
1043Enum step value cannot be zero
1044STRUCT name expected
1045ENDS without STRUCT
1046STRUCT member name is invalid
1047STRUCT member size suffix is invalid
1048STRUCT already defined
1049unused label … (a warning, from -W)
1050Invalid directive
1051Informational text, shown with -v
1052Unknown SNA command: …
1053Unknown NEX command: …
1054Expected NEX command, found: …
1055Expected SNA command, found: …
1056Your own message directive
1057Shebang detected and ignored: …
1058General error: …
1059Memory 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
1062 is a reserved word and cannot be a module name
1063Invalid or missing module name, found
1064ENDMODULE without MODULE
1065MODULE was never closed with ENDMODULE
1066Invalid or missing label after KEEP, found
1067KEEP names , which is not defined
1068Code emitted at … is in ROM and cannot run
1069Code assembled at …, before any ORG set an origin
1070Invalid or missing name after GLOBAL, found
1071GLOBAL names , which is not defined
1072Unknown escape \… in a string or character literal
1073A 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
1076A digit separator must be _, not ' — found after
1077Targets 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
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 address or bank (was 1049, which the unused-label warning kept)
1083NEX 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
1200A Rhai script failed to compile, or the engine raised a fault running one

Documentation