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

Error Handling

All runtime operations that can fail return Result<T, RuntimeError>.

RuntimeError variants

Host errors

These indicate a bug in your code — the host called the API incorrectly.

VariantWhen
InvalidChoiceIndexchoose() called with an index outside the valid range
NotWaitingForChoicechoose() called when story isn’t in WaitingForChoice status
StoryEndedTried to continue a story that has permanently ended
UnknownFlowReferenced a named flow that doesn’t exist
FlowAlreadyExistsTried to spawn a flow with a name that’s already active

Function evaluation & host-directed entry

Raised by the engine→ink direction: calling an ink function from host code (call_function, begin_function_eval), and jumping the story to a path (choose_path_string). See Runtime API.

VariantWhen
FunctionNotFoundcall_function named something that isn’t a function or knot
ArgCountMismatchWrong number of arguments for the target’s declared parameters
FunctionYieldedA host-called function tried to present choices or end the story
AlreadyEvaluatingFunctionA function evaluation is already in progress on this flow
NotEvaluatingFunctionresume_function_eval called with no evaluation in progress
AsyncExternalInCallA function called from the synchronous call_function path hit a deferred external
UnknownPathchoose_path_string given a path matching no knot, stitch, or label
JumpWhileAwaitingExternalTried to jump while the flow is parked on an unresolved external

A function evaluated from host code must run to a return value. FunctionYielded means the ink you called wanted to become the story — present choices, or hit -> END — which the isolated evaluation path cannot honor.

Safety limits

The VM caps anything that accumulates, so malformed bytecode or a runaway loop in the story fails loudly instead of hanging.

VariantWhen
StepLimitExceededOpcode budget exhausted — likely an infinite loop in the story
LineLimitExceededA single turn produced more lines than continue_maximally allows

Story errors

These indicate a problem in the ink source or an unsupported feature.

VariantWhen
TypeErrorType mismatch in an ink expression (e.g., adding a string to a list)
DivisionByZeroDivision or modulo by zero in an ink expression
UnresolvedExternalCallStory calls an external function with no handler provided
RanOutOfContentExecution fell off the end of a knot — usually a missing -> DONE or -> END
UnimplementedThe story uses an opcode not yet supported by the VM

Locale errors

Raised by apply_locale() when a .inkl overlay doesn’t match the program it’s applied to. See Localization.

VariantWhen
LocaleChecksumMismatchThe overlay was compiled against different bytecode — recompile it
LocaleScopeNotInBaseThe overlay carries a scope the base program doesn’t have
LocaleScopeMissingLocaleMode::Strict and the overlay omits a scope the base requires

Internal errors

These typically indicate a compiler bug — the bytecode is malformed.

VariantWhen
DecodeCorrupt or incompatible .inkb file
UnresolvedDefinitionLinker can’t find a referenced definition
NoRootContainerStory has no entry point
StackUnderflowValue stack empty when an operand was expected
CallStackUnderflowNo call frame to return to
ContainerStackUnderflowNo container to pop from the container stack
UnresolvedGlobalGlobal variable lookup failed
CaptureUnderflowOutput capture stack mismatch

Recovery

Host errors are recoverable — fix the calling code and retry. Function-evaluation and locale errors are recoverable in the same sense: the story state is untouched, so correct the call (or recompile the overlay) and try again. Story errors may be recoverable depending on context.

Safety-limit errors abort partway through a turn, leaving the story mid-step; treat the instance as spent and restart it from a snapshot rather than continuing. Internal errors generally indicate broken bytecode and are not recoverable.