Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

What I say

Everything I can say when a program has a mistake in it, and the tip that comes with it. A word in braces is filled in with what’s in your program.

after-rest-needs-default

{param} comes after {rest}..., so it can only be given by name, and it has no value to start with!

Give it one, like {param} = NULL, or move it before {rest}....

allow-rest-needs-function

Only a FUNCTION can take the rest of the modifiers with ..., and this is a {form}!

Put ALLOW(name...) on the function’s own line.

allow-rest-unknown

{function} gives the rest of its modifiers to {name}, but it has no parameter called {name}!

ALLOW({name}...) names one of the function’s own parameters, and it can’t be a rest... one.

argument-given-twice

{name} was given a value for {param} twice!

A parameter can be filled in order, by name, by a modifier or by its BIND list, but only once.

argument-type

{name} needs {expected} for {param}, and it was given {type}!

arguments-need-keyword

I can only take a list of arguments or !! modifiers after a keyword or a function name!

array-item-waits

I couldn’t finish making a new {type} for the array, because its defaults have to wait for something!

Make the object yourself and add it: list + [{type}()].

array-takes-count

I can only take a whole number of items off the end of an array, and this is {type}!

array - 2 takes two items from the end.

array-too-long

Adding {count} items to an array in one go is more than I can hold!

A whole number after + is how many empty items to add. To add the number itself, wrap it: list + [5].

array-too-short

I can’t take {count} items off an array that only has {size}!

array - 1 takes one item from the end. Check how many are there first if it might be empty.

arrow-parameters

I need plain names in front of =>!

Write x => x * 2, or (a, b) => a + b for more than one. For anything fancier, use FUNCTION(a, b = 1) with END FUNCTION.

async-needs-call

ASYNC goes right in front of a call, and this isn’t one!

Write it like answer = ASYNC load_level(1).

async-needs-function

ASYNC can only start a function, and this is {type}!

Reading from an array or a map is quick, so it doesn’t need ASYNC.

async-takes-no-modifiers

ASYNC can’t take !! modifiers here — nobody has told me what they’d mean!

The host sets them up with BIND ASYNC function ALLOW(...).

atomic-inside-function

ATOMIC marks a variable for the whole program, so it can’t go inside a function!

Put the ATOMIC line at the top of a file. Functions can then change the variable as usual.

atomic-needs-global

{name} is a LOCAL here, and only a shared variable can be ATOMIC!

A local belongs to one thread, so nothing else can change it anyway.

atomic-update-calls-function

{name} is ATOMIC, so I change it in one step — and calling {function} in the middle would keep every other thread waiting!

Work the value out on the line before, like n = {function}(...), then use n in the update.

bad-index

I need a whole number or a range to find what you want here, and this is {type}!

list(0) is one item and list(0 ... 2) is the first three. The same goes for the characters of text.

bad-map-key

I can only use a string or a whole number as a map key, and this is {type}!

bind-incomplete

{form} needs a keyword and then the function it runs!

Write it like {form} SHOUT print.

bind-keyword-shape

A {form} keyword is one to four plain words!

DRAW and DRAW LINE both work.

bind-keywords-clash

{bind} allows two different keywords written {keyword}, so I couldn’t tell which one a line means!

Allow just one of them by its namespace, like Steps.{keyword}.

bind-missing-parameter

{bind} leaves out the parameter {name}, and it has no default for me to fall back on!

bind-modifiers-clash

{bind} allows two different modifiers called {name}, so I couldn’t tell which one a script means!

Allow just one of them, or give one a different name.

bind-too-many-arguments

{bind} lists more arguments than {name} takes — it only has {count}!

bind-unknown-function

{bind} names the function {name}, but I can’t find one!

Double-check the name, and that the function is declared somewhere.

bind-unknown-modifier

{bind} allows {name}, but I can’t find a function, a keyword or a namespace with that name!

binder-needs-source

{keyword} has nothing to step through after the =!

Give it an array, a range or a map.

bit-pattern-too-large

{literal} doesn’t fit in 64 bits — that’s all the room I have for one number!

bits-need-integer

{op} works on the bits of a whole number, and this is {type}!

Bits only make sense for whole numbers. x \ 1 drops the fraction from a float.

block-after-then

I can’t open a block after THEN!

Take out the THEN and finish with END IF instead.

block-header-chained

I can’t chain the line that opens a block with ##!

Work the value out on the line before it instead.

block-in-chain

{keyword} opens a block, so it can’t be a stage in a ## chain!

block-never-closed

Looks like this {block} is never closed!

It needs a {closer} to finish it.

cannot-negate

I can only put a - in front of a number, and this is {type}!

cannot-spread

I can’t spread {type} with **!

An array, a coordinate or a vector spreads into arguments in order, and a map fills parameters by name.

case-after-else

CASE ELSE has to be the last case — nothing but END SELECT can come after its lines!

case-needs-value

This CASE doesn’t say what to match!

Try CASE 1, 2, CASE 3 TO 5, CASE IS > 5 or CASE ELSE.

case-without-select

This CASE isn’t inside a SELECT CASE!

A CASE line goes straight inside SELECT CASE value … END SELECT.

chain-value-outside-chain

I only know what _ means inside a ## chain!

chain-value-without-previous

_ is the value from the previous stage — but this is the first stage, so there isn’t one yet!

colon-misplaced

Hmm, this : isn’t somewhere I know what to do with it!

A : only belongs between a map key and its value, like {hp: 100}.

comma-after-keyword

There’s a comma right after {keyword}, before any argument!

Take that first comma out.

comparison-chained

I can only compare two things at a time!

Join two comparisons with AND instead, like a < b AND b < c.

const-inside-function

CONST names a value for the whole program, so it can’t go inside a function!

Put the CONST line at the top of a file or in a NAMESPACE. Inside a function, LOCAL is what you want.

const-needs-global

{name} is a LOCAL here, and only a shared variable can be a CONST!

constant-assigned

{name} is a CONST, so it keeps the value its CONST line gave it!

If it needs to change, declare it without CONST.

coordinate-needs-numbers

A coordinate is made of numbers, and one of these is {type}!

deprecated-function

Heads up! {name} is on its way out and may stop working one day. {note}

division-by-zero

Whoops! You tried to divide by zero — that’s a number no-no even for me!

Make sure the divisor isn’t zero before dividing. You can check with IF x <> 0.

do-closed-by-loop

END {found} can’t close the DO on line {opened}!

A DO block ends with LOOP.

doc-param-unknown

This doc comment describes a parameter called {param}, but {name} doesn’t have one!

Check the spelling against the names between the function’s parentheses.

doc-tag-empty

The !{tag}: line in this doc comment has nothing after it!

Write what it should say after the colon, like /// !returns: the player's score.

else-not-last

ELSE has to be the last part of an IF — nothing but END IF can come after it!

else-without-if

This ELSE doesn’t belong to an IF!

Check whether the IF above it is missing, or already closed.

empty-parentheses

These parentheses are empty!

Put a value inside them, or take them out.

end-mismatch

END {found} doesn’t match the {expected} that was opened on line {opened}!

The innermost open block has to be closed first. Did you mean END {expected}?

end-without-opener

I found END {block}, but there’s no {block} open for it to close!

engine-refused

{reason}

enum-member-assigned

{name} is a member of an ENUM, so it keeps the number its ENUM gave it!

If it needs to change while the program runs, keep it in an ordinary variable instead.

enum-member-twice

An ENUM already has a member called {name}!

Each member needs a name of its own. An ENUM can’t be opened a second time to add the same ones again.

enum-needs-name

An ENUM needs a name, and nothing else on its line!

Write it like ENUM Mode, then its members on the lines after, then END ENUM.

enum-only-names

Only names go inside an ENUM, each with a value if you like!

Write them one to a line or with commas between: idle, playing, paused = 10. One with no value is one more than the one before it.

error-code-taken

The error code {code} is one of my own, so a function can’t declare it!

Pick a different code for this error.

error-code-unknown

ERROR was given the code {code}, but no function declares an error with that code!

Declare it in a doc comment above the function, like /// !{code}: what went wrong.

error-declared-twice

The error {code} is already declared on line {opened} of {file}!

Each error code gets one message. Use a different code, or remove this one.

error-needs-code

ERROR needs a code written as a string, and it was given {type}!

Write it like ERROR("save-missing", {name: name}).

error-tag-needs-function

This doc comment declares an error, but it isn’t sitting above a FUNCTION!

error-tag-shape

I couldn’t read this error line in the doc comment!

Write it like /// !save-missing: I can't find a save called {name}! — the code is lowercase words joined by -.

error-tip-without-message

This tip doesn’t have an error message above it to belong to!

Put the /// !code: message line first, then /// !tip: ... right under it.

evaluate-no-call

There’s no call number {index} on that thread to look at things from!

evaluate-too-long

That ran for so long I gave up on it!

It looks like a loop that never ends.

evaluate-waits

That would have to wait for something, and I can’t wait while the script is stopped!

expression-incomplete

I was expecting a value here, but the expression stops before it’s finished!

This could be a number, a string, a variable or a calculation.

field-name-expected

I need a field name right after the .!

Fields are written like player.hp.

field-outside-type

A field like this only belongs inside a TYPE block!

file-not-read

I couldn’t open {path}! ({reason})

float-too-large

Whoa, {literal} is too big for me to hold in a float!

function-assigned

{name} is a function or a type, so I can’t assign a value to it!

Pick a different name for the variable. A variable can take the name of something built in, but not of a function or a type your script declares.

function-cannot-declare

A function written in place can’t declare {found} inside it!

Declare it outside, and use it from in here.

function-declared-twice

The function {name} is declared twice, and I can’t tell which one you mean!

Rename or remove one of them.

function-not-settable

{name} gives values back, but I can’t assign through it!

Assigning like {name}(...) = value only works for a function the host made settable.

function-takes-no-modifiers

{function} doesn’t allow any modifiers, so nothing can follow it after !!!

A function says which modifiers it takes with ALLOW(...) on its FUNCTION line.

future-not-resolved

This is a future — the answer from an ASYNC call that may not have arrived yet!

Wait for the answer with RESOLVE(...) and use what it gives you.

handler-needs-parameter

{bind} hands {name} something to keep, but {name} has no parameter to take it!

A block or an ASYNC call arrives as the function’s last parameter, so add one — and it can’t be a rest... one.

host-closure-arity

The host declared {name} with {count} parameters, but the Rust closure attached to it takes {given}!

This one is for whoever embeds me: the closure needs one parameter for each one in the declaration.

host-declaration-shape

I need exactly one FUNCTION line in each host function declaration!

host-function-unattached

The host declared the function {name} but never gave me the code to run for it!

This one is for whoever embeds me: attach it with Engine::function.

host-only-declarations

Host declarations can only hold FUNCTION, TYPE, NAMESPACE and the BIND kinds of line — I found something else in here!

if-then-alone

This IF ends with THEN, and nothing comes after it!

An IF on one line puts what to do after THEN. One that opens a block has no THEN: write IF ready, the lines it runs below it, then END IF.

import-inside-block

IMPORT has to stand on its own, outside every block and function!

Move it to the top of the file.

import-not-found

I can’t find the file {path} to import — is the path right? ({reason})

Import paths start from the folder of the file doing the importing, and .crash is added if you leave it off.

import-older-language

{path} is a Crash BASIC 1 file, and I’m Crash BASIC 2 — I only read .crash files!

.bas files belong to the older language. Scripts for me end in .crash, and I add that myself if you leave the ending off.

index-needs-argument

I need to know which item to change!

Put an index or a key in the parentheses, like scores(0) = 10.

index-out-of-bounds

You tried to reach item {index}, but that’s past the edge of the array — it has {size}!

Arrays start at 0, so an array with 3 items has items 0, 1 and 2. To make one longer, use PUSH list, item or list = list + [item].

integer-too-large

Whoa, {literal} is too big for me to hold in an integer!

keyword-assigned

{keyword} is a keyword, so I can’t assign to it!

If you meant to pass it a comparison, wrap the comparison in parentheses.

keyword-bound-twice

The keyword {keyword} is bound twice!

A keyword can only belong to one function.

keyword-outside-block

{keyword} is a keyword only inside {blocks}, and this line isn’t in one!

Move it inside one, or put its namespace in the ALLOW of the function this line is in.

loop-two-tests

This loop is tested twice: once on the DO on line {opened}, and again on its LOOP!

Keep one. A test on DO is made before each pass, a test on LOOP after it.

loop-without-do

This LOOP doesn’t have a DO to go back to!

map-entry-needs-value

This map entry has a key but no value!

Put a value after the :.

map-entry-shape

I couldn’t read this map entry!

Each entry is written key: value, with commas between entries.

map-key-shape

I can’t use this as a map key!

A key is a bare word, a “string”, or an expression in (parentheses).

matrix-operands

I can’t use {op} on {left} and {right}!

@* multiplies a matrix by a matrix, a number, a coordinate or a list of numbers. @+ and @- take two matrices, or two lists of numbers, of the same shape.

matrix-shape

I can only multiply a matrix whose rows are all the same length, with nothing in them but numbers!

A matrix is an array of rows, like [[1, 0], [0, 1]]. (2, 2):INTEGER makes one full of zeros.

matrix-shapes-differ

I can only add or subtract two of the same shape — the left one is {left} and the right one is {right}!

Part is matched with part, so both need the same number of rows and the same number in each row.

matrix-size-mismatch

I can’t multiply these — the left one is {left} across and the right one is {right} down, and those have to match!

Each row on the left meets each column on the right, so the left needs as many columns as the right has rows. A coordinate stands as a column on the right of a matrix and as a row on its left.

method-without-type

The method {name} belongs to a type I can’t find!

Declare the TYPE in the same namespace as its methods.

missing-argument

{name} needs a value for {param}, and it wasn’t given one!

modifier-given-twice

{keyword} was given {modifier} twice, and I can’t tell which one you mean!

modifier-needs-map

A modifier after !! has to give me a map, and this one gave me {type}!

A modifier is a function that returns a map, like {thickness: 2}.

modifier-not-allowed

{keyword} doesn’t take the modifier {modifier}!

Add it to the keyword’s ALLOW(...) list if it should.

modifier-takes-one-value

{keyword} takes {modifier} with one value after it, like {modifier}(10)!

named-arguments-need-function

I can only fill parameters by name when calling a function, and this is {type}!

namespace-not-value

{name} is a namespace — a name for a group of things, not a value I can pass around!

Reach into it with a dot, like {name}.something.

next-mismatch

NEXT closes a loop, but the innermost open block is the {expected} from line {opened}!

Close that one first, with END {expected}.

next-without-loop

I found NEXT, but there’s no loop open for it to close!

NEXT closes a block like FOR, the same as END FOR does.

next-wrong-names

NEXT {found} doesn’t match the {keyword} on line {opened}, which steps through {expected}!

Write NEXT {expected}, or just NEXT.

no-fields

I tried to look up .{field}, but this value is {type} and doesn’t have fields!

no-place-for-change

I changed part of {type}, but it came from somewhere I can’t put the new one back!

Keep it in a variable first, change the variable, then use that.

not-callable

I can’t call or look inside {type}!

Parentheses after a name call a function, or read from an array or a map.

not-indexable

I can’t store a value inside {type}!

Only arrays and maps hold other values.

not-iterable

I can’t step through {type}!

A block like FOR steps through an array, a range or a map.

outside-block

{function} only works inside a {block} block, and there isn’t one open around this line!

Move this line between {block} and END {block}.

outside-loop

{word} only works inside a loop, and there’s no loop around this line!

push-import-unknown

I can’t bring {path} into a script that’s already running!

Restart the script to import a new file.

push-too-many-variables

That’s more new variables than I kept room for in a running script!

Restart the script to pick them all up.

push-type-changed

{name} already has values out there, so I can’t change its fields while the script is running!

Its fields are {expected}. Keep them as they are, in that order, or restart the script.

range-chained

A range or a vector has exactly two ends — I can’t chain a third one on!

range-has-fractions

I can only count through a range of whole numbers, and {range} has fractions in it!

0 ... 3 counts 0, 1, 2 and 3. A range like 0.1 ... 0.3 is the span between two numbers, for things like where in a sound to start and stop.

rest-given-twice

{rest}... and {param}... both take the rest, and I can’t tell where one ends!

Keep one ... parameter.

rewrite-name-twice

This REWRITE shape uses {{name}} twice!

Give each part of the shape a name of its own. You can write a name as often as you like after =>.

rewrite-needs-word

A REWRITE shape has to start with a word, so I know which lines to try it on!

Put the statement’s own word first, like REWRITE PLAYMP3 {name} LOOP => ....

rewrite-never-settles

I kept rewriting this line and never got to the end of it! The last rule I used was REWRITE {form}.

What a rule makes is tried against the rules again. Make sure what comes after its => doesn’t fit its own shape.

rewrite-shape

I can’t read this REWRITE line!

Write the shape, then =>, then what it becomes: REWRITE PLAYMP3 {name} LOOP => PLAYMP3 {name} !! loop.

rewrite-unknown-name

After => this REWRITE asks for {{name}}, but its shape has no part called that!

Check the spelling against the names in braces before the =>.

rewritten-syntax

A REWRITE rule turned this line into {found}, and I can’t read that — I got stuck at {near}!

Look at the rule whose shape fits this line. What comes after its => has to be something I can read once the names are filled in.

scope-takes-one-name

{keyword} runs its block once, so it only has one value to give — I found two names before the =!

Write it like {keyword} name = ....

select-needs-case

Nothing can come between SELECT CASE on line {opened} and its first CASE!

Start with a line like CASE 1, or CASE ELSE for everything.

select-needs-value

SELECT CASE needs one value to look at!

Write it like SELECT CASE score, then a CASE line for each thing it could be.

self-outside-method

SELF only means something inside a method, and this line isn’t in one!

A method is declared with its type’s name, like FUNCTION Unit::Heal(amount).

single-expression-expected

I was expecting just one value here, but I found a list!

sized-needs-count

An array’s size has to be a whole number, or a coordinate of them for rows of rows, and this is {type}!

10:INTEGER is ten zeros. (4, 3):INTEGER is four rows of three.

spread-in-collection

I can’t spread with ** inside {where}!

** only works on the arguments of a call or a keyword.

spread-misplaced

I can only spread with ** at the very start of an argument!

Write it like DRAW **corners.

spread-needs-value

** needs something to spread!

Put an array, a coordinate or a map right after it.

stage-ignores-chain-value

This stage never uses _, so the value from the stage before it would be lost!

Put _ wherever that value should go.

statement-does-nothing

This line doesn’t do anything!

A statement needs to assign a value, use a keyword, or call a function.

step-is-zero

A step of 0 would never get anywhere!

Give step a number that isn’t 0, like !! step(2).

syntax

I got confused by the syntax here — I got stuck at {near}.

Double-check the spelling and structure of this line.

syntax-at-end

This line stops before it’s finished!

Look for a missing closing bracket or quote mark. Every (, [, { and " needs a partner.

text-block-missing

{keyword} holds a block of text, so it has to start a line of its own!

Write {keyword} at the start of a line, its text on the lines after it, then END {keyword}.

text-block-unclosed

{keyword} starts a block of text here, but I can’t find the END {keyword} that finishes it!

Put END {keyword} on a line of its own after the text.

text-out-of-bounds

You tried to reach character {index}, but that’s past the edge of the text — it has {size}!

Characters start at 0, so text with 3 characters has characters 0, 1 and 2. LEN(text) says how many there are.

timer-needs-one-time

A timer is after a time or every so often, and this one has both!

Keep one of them. For a wait and then a beat, start the every timer from inside an after one.

too-many-arguments

{name} takes {count} arguments at most, but it was given {given}!

type-declared-twice

The type {name} is declared twice, and I can’t tell which one you mean!

Rename or remove one of them.

type-mismatch

I can’t use {op} on {left} and {right}!

+ adds numbers, or joins text when either side is a string. The other operators work on numbers. Coordinates can be added and subtracted, or scaled by a number. For matrices, use @*, @+ and @-.

type-only-fields

I can only keep fields inside a TYPE!

Fields are written like hp AS INTEGER = 100. Everything else goes after END TYPE.

type-values-need-map

To set fields when making a {name}, I need a map, and this is {type}!

Write it like {name}({hp: 50}).

unexpected-token

Hmm, I wasn’t expecting {found} here!

Check whether something is missing just before it, like an operator or a comma.

unknown-field

{type} doesn’t have a field called {field}!

Check the spelling against the fields listed in the TYPE.

unknown-in-namespace

{name} doesn’t have anything called {field}!

Check the spelling, or look inside NAMESPACE {name} to see what it holds.

unknown-name

Hmm, I don’t know the name {name}! Nothing ever gives it a value.

Double-check the spelling, or give it a value first with {name} = ....

unknown-parameter

{name} doesn’t have a parameter called {param}!

Check the names in the map or the modifier against the function’s parameters.

unknown-type

Hmm, I don’t know a type called {name}!

The built-in types are ANY, INTEGER, FLOAT, STRING, COORDINATE, VECTOR, RANGE, ARRAY, MAP, FUNCTION, FUTURE and ERROR. Anything else needs its own TYPE.

unknown-word

Hmm, I don’t know the word {word}! It isn’t a keyword or a function that’s been declared.

Double-check the spelling, and that whatever declares it has been imported.

value-read-only

{name} is a value I work out each time you read it, so there’s nothing to assign to!

Pick a different name for the variable.

value-takes-arguments

{name} is read like a variable, so it can’t need the argument {param}!

Give {param} a default, or take the !value line away and call it with parentheses.

vector-needs-coordinates

Each end of a vector is a coordinate, and this is {type}!

wend-without-while

I found WEND, but there’s no WHILE open for it to close!

WEND closes a WHILE block, the same as END WHILE does.

wire-cannot-carry

I can’t send {type} to another interpreter — it only means something here!

For a future, RESOLVE it first and send the result.

wire-loop

I can’t send this, because it holds itself somewhere inside — I’d be writing it out forever!

Send the parts separately, or break the circle before sending.

wire-other-script

What arrived talks about a function or type this script doesn’t have — the other side must be running different code!

Both interpreters have to load exactly the same script. Compare their fingerprints before they talk.

wire-too-deep

This value is nested deeper than I can send in one go!

wire-unreadable

What arrived from the other interpreter isn’t a value I can read!

The message may have been cut short or changed on the way.