Error messages
Every error message a program can show, grouped by kind, with what it means and the usual fix.
When something goes wrong, the computer prints a red line and goes back to the prompt. This page lists the messages of the game, grouped by kind, with what each one means and how it is usually fixed. The messages are always in English, whatever the language of the game. To find one, search the page with your browser (Ctrl+F) for a few words of it.
Reading an error
> pump pump:4: attempt to index a nil value (local 'tank')
pumpis the file where it happened (games/snake/mainfor a file in a folder,brassfor a line typed in the interactive interpreter).4is the line. Open the file withedit pump: the editor shows the line numbers.- The rest is the message. Between parentheses, the error often names the variable or the field involved: here the local variable
tank.
There are two moments for an error:
- Compile errors are found before the program starts, when the whole file is read. Nothing runs: fix the line and run the file again.
- Runtime errors happen while the program runs, when a line does something impossible. The program stops there; what it did before (redstone outputs, files written) stays done.
A runtime error can be caught with pcall, which returns a table instead of stopping the program. The message then starts with the file and the line, just like on the screen. Your own errors, raised with error, work the same way:
local function take(count)
if count > 64 then error("a stack holds 64 items at most") end
return count
end
local r = pcall(take, 100)
print(r.ok)
print(r.error)false snippet:2: a stack holds 64 items at most
pcall catches every runtime error of this page, not compile errors, and not Ctrl+T. See Errors and debugging.
Library functions name themselves without their library: an error about 'write' can come from fs.write, and 'set' from rs.set, link.set or a peripheral method. The line number tells which call it was.
Compile errors
The program does not start. The line given is where the compiler noticed the problem, which is sometimes a little after the real mistake (a missing end is only noticed at the end of the file).
| Message | What it means | Usual fix |
|---|---|---|
'then' expected near 'print' | A word or a symbol is missing where the compiler names it. The same message exists for do, =, ), ], in... | Add what is named: if x > 1 then, while running do, for i = 1, 10 do. |
'end' expected (to close 'if' at line 3) near <eof> | A block opened at that line never ends. Also for function, for, while, do, and 'until' for repeat, ')' for (, '}' for {. | Add the missing end (or ), }). Indent your code to see which block is open. |
'<eof>' expected near 'end' | One end too many: the file should stop there. | Remove the extra end, or the else that is not in an if. |
unexpected symbol near ')' | A value was expected and something else came: print(1, ), x =, an operator with nothing before it. | Complete the expression. |
unexpected symbol '&' | A character Brass does not use: &, |, ?, @, $... | and / or instead of && / ||; remove the character. |
unexpected symbol '!' (use 'not') | !x is not Brass. | not x. (!= is fine: it means ~=.) |
unexpected symbol '~' | A ~ alone. | ~= for "different", not for "not". |
syntax error near '+' | A line that is neither an assignment nor a call, like count + 1 alone or a bare variable name. | count = count + 1, or print(count + 1). |
cannot assign to this expression | Something on the left of = that cannot receive a value: f() = 1, a + b = c. | Assign to a variable or a field: x = ..., t.k = .... |
ambiguous syntax (function call x new statement) near '(' | A line starts with ( right after a line ending with a value: Brass cannot tell whether it is a call. | Put the two lines together, or start the line differently (local v = (a or b)). |
a function returns a single value (return a table instead) | return a, b. | return {x = a, y = b}, then read r.x and r.y. |
'end' expected after return near 'print' | Code after a return in the same block. | return must be the last line of its block. Move the code before it. |
cannot capture local 'x' of an enclosing function | A function written inside another uses a local of the outer function. Brass has no closures. | Pass the value as a parameter, or declare the variable at the top of the file (chunk-level locals are fine). |
cannot assign to a function's own name from inside it | A local function declared inside another function assigns to its own name in its body (local function step() step = nil end). | Use another variable. |
'break' outside a loop | break that is not inside while, for or repeat. | Use return to leave a function. |
variable arguments ('...') are not supported | function f(...). | Take a table: f({1, 2, 3}). |
a generic 'for' takes at most 2 variables | for a, b, c in .... | Two variables at most: for k, v in pairs(t). |
a generic 'for' takes a single iterator expression | The Lua form for k, v in next, t. | for k, v in pairs(t) do. |
unfinished string | A string with no closing quote before the end of the line. | Close the quote. For several lines, use "\n" or [[ ... ]]. |
unfinished long string or comment | [[ or --[[ never closed by ]]. | Add the ]]. |
malformed number near '12p' | A number glued to letters (12px), 0x without digits, 1e without exponent. | Separate the number, or fix it. |
invalid escape sequence '\q' | A backslash before a letter Brass does not know. Known: \n \t \r \0 \\ \" \' and \xNN. | For a backslash itself, write \\. |
hexadecimal digit expected in escape sequence | \x not followed by two hexadecimal digits. | \x41 is "A". |
too many nested levels | More than 200 blocks or parentheses inside each other. | Cut the code into functions. |
program too complex | The compiler ran out of room (reported at line 0). | Split the program into functions or files. |
Runtime errors
The program stops at that line. Most of these come from a variable that is nil when the program expected a value: a misspelled name, a reading that returned nil, a peripheral that is not there.
| Message | What it means | Usual fix |
|---|---|---|
attempt to perform arithmetic on a nil value | + - * / // % ^ or a minus sign on something that is not a number (also a string value, a table value, a boolean value...). Text is never turned into a number by itself: "10" + 1 fails. | Check that the value exists (if x then), convert text with tonumber. |
attempt to concatenate a nil value | .. with something else than text or a number (a table value, a boolean value...). | tostring(v) around the value. |
attempt to get length of a number value | # on something else than a string or a table. | Use # on the text or the list itself. |
attempt to index a nil value (global 'chest') | x.y or x[k] when x is not a table. The end names x: global, local, field 'name'. Typical causes: a misspelled name, peripheral.wrap that found nothing, a library this computer does not have (net on a Transistor Mainframe). | Check the name, check for nil after peripheral.wrap / peripheral.find, check the computer. |
attempt to index a string value with a number key | s[1] on a string. | string.sub(s, 1, 1). |
attempt to call a nil value (global 'prnt') | Calling something that is not a function: a typo, a function defined further down the file than the call, a method the block does not have. Also (field 'name'), (method 'name'). | Fix the name; define functions before the code that runs them. |
an iterator can only be used in a 'for' loop | Calling the result of pairs(t) or ipairs(t) directly. | for k, v in pairs(t) do. |
attempt to compare number with nil | <, >, <=, >= between values of different kinds, or that cannot be ordered (attempt to compare two table values). Also raised by table.sort on a mixed list. | Compare two numbers or two strings; tonumber first; give table.sort a comparison function. |
'for' initial value must be a number | A numeric for whose start is not a number. Also 'for' limit must be a number and 'for' step must be a number. | Check the values, often a nil variable. |
'for' step is zero | for i = 1, 10, 0. | A step that is not zero. |
use pairs() or ipairs() to iterate a table with two variables | for k, v in t. | for k, v in pairs(t) or ipairs(t); for v in t (one variable) works. |
attempt to iterate over a nil value | for v in x when x is not a table. | Check that x exists. |
table index is nil | Writing t[k] = v with k equal to nil. Reading t[nil] is fine (it gives nil). | Check the variable used as the key. |
table index is NaN | t[0/0] = v. | Check the computation of the key. |
assertion failed! | assert(value) with a false or nil value and no message. | Give assert a message: assert(chest, "no chest on the left"). |
| your own message | error("..."), or assert(value, "..."). error() with nothing prints nil. | This is your program speaking. |
internal error: ... | A bug of the mod, not of your program. | Report it with the program that causes it. |
Terminated | Not an error: the player pressed Ctrl+T or the Stop button. |
Library arguments
A library function received the wrong kind of value. #1 is the first argument, #2 the second.
| Message | What it means | Usual fix |
|---|---|---|
bad argument #1 to 'set_cursor' (number expected, got no value) | An argument has the wrong type. got no value: it is missing or nil; got string: text where a number was expected, and so on. Also string expected, table expected, boolean expected. | Check the order and the type of the arguments in the function's page. |
bad argument #2 to 'set' (number has no integer representation) | A whole number was expected and a decimal came (7.5), or infinity. | math.floor, math.round. |
bad side 'up' (front, back, left, right, top, bottom) | rs only knows these six faces. | "top" for up, "bottom" for down. |
bad argument #1 to 'set_fg' (color must be 0..15) | term.set_fg and term.set_bg take numbers from 0 to 15. | term.colors.red, or see Colours. |
bad argument #3 to 'pixel' (unknown colour 'grey': white, orange, ..., none) | A colour name gfx does not know. The message lists the 16 names and none. | "gray", "light_gray": the names are the Minecraft dyes. |
bad argument #3 to 'pixel' (colour (0..15 or a name) expected, got no value) | The colour of a gfx function is missing or of the wrong type. | Give a number from 0 to 15 or a name. |
bad argument #3 to 'image' (row 2 is not a string) | A row of gfx.image is not text. | Each row is a string like "0ff0". |
bad argument #1 to 'label' (at most 32 characters) | os.label with a name too long. | 32 characters at most. |
bad argument #2 to 'tonumber' (base out of range) | The base of tonumber must be from 2 to 36. | tonumber("ff", 16). |
bad argument #1 to 'type' (value expected) | type() with no argument. | type(x). |
bad argument to 'random' (interval is empty) | math.random(m, n) with m above n (or math.random(0)). | Check the bounds. |
bad argument #1 to 'char' (value out of range) | string.char takes codes from 0 to 65535. | Check the code. |
invalid conversion '%q' to 'format' | A % code string.format does not know, a width of more than two digits, or a % at the very end. | %d %i %f %s %x %X, %% for the sign itself. |
bad argument #2 to 'format' (no value) | Fewer values than % codes. | One value per % code. |
bad argument #2 to 'format' (number has no integer representation) | %d or %x with a decimal number. | %f, %.1f, or round first. |
bad argument #2 to 'insert' (position out of bounds) | table.insert(t, pos, v) with pos outside 1 to #t + 1. Also 'remove' (1 to #t). | Check the position. |
wrong number of arguments to 'insert' | table.insert(t) without a value. | table.insert(t, value). |
invalid value (at index 3) in table for 'concat' | table.concat met something else than text or a number (or a hole) at that index. | Keep only strings and numbers in the list, or convert with tostring. |
bad argument #2 to 'sort' (function expected, got string) | The second argument of table.sort must be a function. | table.sort(t, function(a, b) return a > b end). |
Files and import
| Message | What it means | Usual fix |
|---|---|---|
no storage medium | fs or import with no medium in the computer. | Insert one (right-click the computer with it). |
bad argument #1 to 'write' (invalid file name 'my notes') | A file or folder name with a forbidden character. Names use letters without accents, digits, _, . and -, from 1 to 32 characters, and cannot be . or ... | my_notes. |
bad argument #1 to 'read' (path too long (128 characters at most)) | The whole path is longer than 128 characters. | Shorter names, fewer folders. |
bad argument #1 to 'list' (no folder above the root) | A path with more .. than folders. | Check the path, fs.cwd() says where you are. |
invalid file name '' | A file operation on the root itself, like fs.write("/", text). | Give a file name. |
not enough space | The medium is full. | fs.free() says what is left. Delete files, or use a bigger medium. |
too many files (1024 at most) | A medium holds 1024 files and folders at most. | Delete files, or group data in fewer files. |
no folder 'logs' | fs.list on a folder that does not exist. | fs.make_dir("logs") first, or check with fs.is_dir. |
'logs' is a file | A folder was expected (fs.list, fs.make_dir, moving a folder onto it). | Use another name. |
'logs' is a folder | A file was expected: fs.write or fs.append on a folder, or fs.move / fs.copy onto an existing folder. | fs.move and fs.copy take the full new path: fs.move("log", "old/log"). |
'notes' is a file, not a folder | The path goes through a file as if it were a folder (notes/today while notes is a file). | Rename one of them. |
no file 'report' | fs.move or fs.copy from a path that does not exist. | Check with fs.exists. |
a folder cannot go inside itself | Moving or copying a folder into itself. | Choose another destination. |
a file cannot be copied onto itself | fs.copy with the same path twice. | Choose another name. |
the root cannot be deleted | fs.delete("/"). Also the root cannot be moved or copied. | Delete the files one by one. |
cannot import 'utils': no such file | import did not find the file. The path is relative to the folder of the file that imports. Also it is a folder, or a path error after the colon. | Check the name and the folder; /lib/utils from the root. |
circular import: 'a' is still being imported | Two files import each other. | Move what they share into a third file. |
A missing file is not an error for fs.read (it returns nil), fs.size (nil) or fs.delete (false). A compile error inside an imported file keeps the name and line of that file: lib/utils:4: 'then' expected near 'print'.
Network
| Message | What it means | Usual fix |
|---|---|---|
attempt to index a nil value (global 'net') | The Tube Computer and the Transistor Mainframe have no network. | A Minicomputer or newer. |
message too large | A message holds more than 2048 values or more than 32768 characters of text in all. | Send less, or in several messages. |
cannot send a function | Only numbers, strings, booleans and tables of them travel. | Send data, not functions. |
table is too deep (or cyclic) to convert | Tables nested more than 32 levels deep, or a table that contains itself. | Flatten the data. |
bad argument #1 to 'send' (number expected, got string) | net.send takes the id first, then the data. | net.send(id, data, channel). |
Not errors: net.send returns false when the computer is out of reach, off, or its receive buffer is full, and net.receive(timeout) returns nil when nothing came.
Peripherals and blocks
| Message | What it means | Usual fix |
|---|---|---|
attempt to index a nil value (local 'light') | peripheral.wrap or peripheral.find returned nil: nothing to talk to there. | Check the face or the type, test if light then. |
no peripheral 'left' | peripheral.call on a face or a name with no block to talk to. | peripheral.list() shows the names. |
peripheral 'left' has no method 'set' | That block has no such method. | peripheral.type(name), then the page of that block. |
peripheral is not loaded | The block is in a chunk that is not loaded. | Keep the chunk loaded, or wait. |
traffic light removed | The wrapped block is gone, or replaced. Also monitor removed, radio removed, sensor removed, burner removed, not a kinetic block anymore, not an inventory anymore, not a tank anymore. | Wrap it again once the block is back. |
bad aspect 'blue' (off, red, red_amber, amber, green, flashing) | Not an aspect of the Traffic Light. | One of the six names. |
only Wi-Fi routers have an SSID | set_ssid on a Radio Modem. | Use a Wi-Fi Router. |
redstone link not ready | The Redstone Link could not be read: it is not set up yet. | Try again a moment later. |
set_speed needs a Rotation Speed Controller | set_speed on another kinetic block. | Wrap the Rotation Speed Controller itself. |
no inventory 'chest' | The target of push is not a name of an inventory the computer can reach. | peripheral.list("inventory") gives the names. |
bad item id 'Iron Ingot' | link takes item ids, not display names. Also unknown item 'minecraft:iron' for an id that does not exist. | "minecraft:iron_ingot": F3+H shows the ids in tooltips. |
too many link frequencies (max 32) | The computer already uses 32 Redstone Link frequencies. | Reuse frequencies; reboot to release them all. |
burner not ready | The Hot Air Burner could not be read: it is not set up yet. | Try again a moment later. |
this version of Simulated has no getXAngle | Create Simulated changed: a method the mod reads is missing (the name varies). Also this version of Simulated has no spring limit, sensor error: .... | Update Create: Computing Ages or use the matching version of Create Aeronautics. |
Memory and limits
| Message | What it means | Usual fix |
|---|---|---|
out of memory | The live data of the program is larger than the memory of the computer. | Drop what you no longer need (t = nil), keep fewer and shorter strings, os.memory() to watch it, or a bigger computer. |
stack overflow | More than 200 calls inside each other, usually a function calling itself without end. | Add the stop condition, or turn the recursion into a loop. |
string too long | A text over 65536 characters (.., string.rep, string.format, table.concat). | Write in pieces, to a file with fs.append. |
too many timers | 256 timers are already waiting. | Start a new timer only when the previous one fired. |
The other limits have their own messages above: too many files, path too long, message too large, too many link frequencies, too many nested levels. Every number is on Limits.
Shell messages
These come from the command line, not from a program. Some of them are shown in the language of the player.
| Message | What it means | Usual fix |
|---|---|---|
No such program: pmp | No file of that name in the current folder. | ls lists the files. |
No such file: pmp | run on a file that does not exist. Also No such file for cat, rm, cp, mv. | Check the name. |
'games' is a folder: cd games | The name typed is a folder. | cd games, then the program's name. |
No folder 'games' | cd or ls on a folder that does not exist. | mkdir games creates it. |
No storage medium: right-click the computer with one | The command needs a medium. | Insert one. |
'games' is not empty: rm -r games | rm refuses to delete a folder with files inside. | rm -r games. |
'games' already exists | mkdir on an existing name. | Another name. |
Usage: cp <from> <to> | The command misses an argument. | Follow the usage shown. |
No library 'gfx' | help gfx on a computer without that library. | help lists the libraries this computer has. |