Error Handling
Every error carries a status code and a message. Scripts run from a file
include line numbers in error messages.
Error categories
Lexical
UNEXPECTED_CHARACTER
UNTERMINATED_STRING
Syntax
EXPECTED_TOKEN
UNEXPECTED_TOKEN
UNEXPECTED_EOF
INVALID_STATEMENT
INVALID_FUNCTION_DEF
INVALID_LITERAL
Semantic
UNKNOWN_VARIABLE
UNKNOWN_FUNCTION
UNDEFINED_KEY
ARRAY_INDEX_OUT_OF_RANGE
NOT_CALLABLE
REASSIGN_CONSTANT
REASSIGN_RESTRICTED
MODIFY_CONSTANT
MODIFY_RESTRICTED
INVALID_ACCESSOR
INVALID_OPERATOR
INVALID_ITERABLE
INVALID_ASSIGNMENT_TARGET
INVALID_ARGUMENT_COUNT
INVALID_OPERAND_TYPE
INVALID_ARGUMENT
INVALID_CONVERSION
TYPE_ERROR
Runtime
DIVISION_BY_ZERO
MODULO_BY_ZERO
STACK_OVERFLOW
ARITHMETIC_ERROR
OUT_OF_MEMORY
STEP_LIMIT_EXCEEDED
TIME_LIMIT_EXCEEDED
TIMEOUT
CONNECTION_FAILED
IO_ERROR
OPERATION_FAILED
ASSERTION_FAILED
RUNTIME_ERROR
UNSUPPORTED
File
FILE_NOT_FOUND
FILE_UNREADABLE
IMPORT_NOT_FOUND
IMPORT_READ_FAILED
PLUGIN_LOAD_FAILED
Common failure modes
# division by zero
print(1 / 0) # DIVISION_BY_ZERO
# reassigning a constant
const pi = 3.14
pi = 3 # REASSIGN_CONSTANT
# missing variable
print(undefined_name) # UNKNOWN_VARIABLE
# incompatible comparison
print(1 == "one") # TYPE_ERROR
# deep recursion
fn boom() { return boom() }
boom() # STACK_OVERFLOW (limit 256)
# failed assertion
std.assert.assert_eq(1, 2) # ASSERTION_FAILED (not RUNTIME_ERROR)
Runtime failures distinguish what went wrong so scripts (and hosts) can
react accordingly:
CONNECTION_FAILED— the channel could not be established: refused
connects, failed binds/listens, unresolvable hosts, unreachable daemons
(D-Bus, PipeWire, PulseAudio).IO_ERROR— an established channel or filesystem call failed mid-stream:
failed reads/writes, dropped connections, oversized HTTP bodies.OPERATION_FAILED— the call reached the other side, which said no:
rejected D-Bus methods, refused device parameters, codec errors, failed
process spawns.ASSERTION_FAILED— anstd.assert.*check failed.TYPE_ERROR— operands of a compatible kind but incompatible types
(1 == "one", a pipe returning a different type than its receiver).INVALID_OPERAND_TYPE— a function/builtin got an argument of the wrong
type (len(42),std.string.upper(42)).INVALID_OPERATOR— internal only (the parser produced an operator the
evaluator doesn’t implement); scripts never trigger it directly.TIMEOUT— anawaitdeadline passed (see below).STEP_LIMIT_EXCEEDED/TIME_LIMIT_EXCEEDED— a sandboxed engine’s step
budget or wall-clock deadline fired (see Embedding).
Catchable like any error — the engine stays usable afterwards.RUNTIME_ERROR— anything else; the message carries the details.
Errors from async work
Errors raised on background tasks (spawned fibers, network receive loops,
timers) are recorded and surfaced rather than lost:
std.async.await(future)re-throws the task’s error (as
Async error: <message>) with the task’s original status — a task that
fails an assertion surfacesASSERTION_FAILED, not a flattened
RUNTIME_ERROR. Use this forspawn/deferand single-shot
timers, whose errors live on the returned future.std.async.await(future, timeout_ms)throwsTIMEOUTwhen the deadline
passes first.- Background objects with no caller record the most recent failure and expose
it vialast_error(): repeating-timer handles (handle.last_error()),
and thestd.netobjectstcp_client,tcp_server,udp,websocket, and
http_server(nilwhen there is none).
See std.time for details on which surface applies to each
kind of background work. Concurrency errors in particular are covered in
Concurrency — Errors.
Assertions
std.assert is the lightweight way to fail fast in tests and preconditions:
std.assert.assert(x > 0, "x must be positive") # throws on failure
std.assert.assert_eq(40 + 2, 42) # equality check
std.assert.assert_throws(fn() { 1 / 0 }) # expects an error
A failed assertion throws a normal Scrii error with a message, and in async
tasks it is stored on the future and re-thrown by await — see
std.assert for the full API.
Embedding
Host callbacks that throw from C++ surface in the script. Prefer throwing
ScriptError{status::..., msg} so scripts receive a clean status and
message. See Embedding.