Errors and Diagnostics​

Diagnostics as you read them​

An error has one of two shapes, and the shape says when it happened: a static listing before anything runs, or a run-time text that catch sees.

The static listing (before anything runs)​

jaiscript
int x = 5;
x = "hello";                  // typed to typed: the load fails, nothing runs
print("never printed");
output
jaiscript: static check failed:
<script>:2:3: error: cannot assign 'string' to 'x' declared 'int' (declared at 1:5)
    x = "hello";                  // typed to typed: the load fails, nothing runs
      ^

The shape is FILE:LINE:COL: error: MESSAGE, then the source line, then a caret.

PartRule
FILEThe unit's resolved path (the root file, an import, an include); <script> for source text handed to execute().
MessageLowercase, except the few that reuse a run-time text and keep its capital (Cannot access private member 'x' of class 'C', Cannot access private constructor of class 'C'). One about a declared name ends with (declared at LINE:COL).
A failed loadHands the host one jai::static_check_error whose what() is the whole listing (sorted by location, deduplicated, capped at 100). Nothing has executed.
WarningsShadowing, a copying cast: the same shape with warning:; they never stop the load. The runner lists them under --warnings; a host reads them from last_check_diagnostics().
A syntax errorThe same shape under parse failed:, thrown as jai::parse_error. The parser lists every syntax error in source order (it resumes after each); no check runs until the source parses.

Checked at load, by site​

Each row is an error whenever the types involved are declared or inferred (auto holds the type it inferred). Chapter: Strict Checking.

SiteWhat is checkedExample message
Namesevery identifier is declared where the use can see it; top-level code sees only what is declared above it (top-level order), a function body also what is declared below; a qualified name exists in its namespaceuse of undeclared identifier 'totl'; no member 'sqroot' in namespace 'math'
Declared typesevery spelled type names a class, enum or builtin type, inside container and handle types toounknown type 'vec2'; did you mean 'math::vec2' (using math::vec2;)?
Redeclarationone declaration of a variable per scope, the top level of a file includedredeclaration of 'a' in the same scope
Storesa declaration, =, op=, a field, a static, a return and a pushed or literal element against the slot's type, by the conversion tablecannot assign 'string' to field 'hp' declared 'int'
Float into intrefused at every slot where both types are visible, a store through an int& and a coroutine's yield includedcannot initialize 't' declared 'int' with 'float': cast<int>(x) truncates toward zero, math::ifloor(x) rounds down
A vec into an ivecrefused at every slot where both types are visible (a variable, a parameter, a return, a field, an element, a store through a reference); an ivec widens into a veccannot initialize 'cell' declared 'math::ivec2' with 'math::vec2': cast<math::ivec2>(v) truncates each component toward zero
Text or a container into boola declared bool slot refuses a string, an array and a map; conditions keep truthinesscannot initialize 'b' declared 'bool' with 'string': write !x.empty() or an explicit comparison
Class valuesnever null, in a variable, parameter, field, static, return or element; a class cannot hold itself by value, directly, through another class or through a basecannot initialize 'h' declared 'Hero' with 'null': a 'Hero' is never null; declare 'shared_ptr<Hero>' (or var) for a slot that can be empty
Enumsan enum is a type: an int or another enum's value does not enter its slots, ++ and += do not apply, and a value must be one the enum declares (Enums)cannot initialize 'd' declared 'Dir' with 'int': cast<Dir>(n) converts an int that is one of its values
Callsa function, method or constructor the checker knows, another file's and a namespace's (ns::f) included: argument count (defaults counted) and each argument; with overloads, an error only when none fits'fib' expects 1 argument(s), got 2; argument 1 of 'game::add': cannot pass 'string' to 'n' declared 'int'
Builtin callsa builtin method's and a math:: function's arguments against the shapes the API reference states: a number, text, an array, a map, a function, a vector or color. A parameter that takes several shapes is not checkedargument 1 of 'math::sqrt': cannot pass 'string' where a number is expected; argument 1 of 'substr' on 'string': cannot pass 'string' where a number is expected
Host callsa function the host registered and a method it bound: argument count and each argument against the C++ signature (a number for a number, text for a std::string, an array, a map). A script class below the bound class that declares the method leaves the call to run time'host_scale' expects 2 argument(s), got 1; no overload of 'Probe.set' accepts these argument types
Default argumentsa default cannot read a parameterdefault value of 'b' names parameter 'a': a default cannot read a parameter
print / formatthe literal format text's placeholders against the arguments that follow it, none includedthe format text of 'print' has 2 placeholder(s) for 1 argument(s); the format text of 'print' has 1 placeholder(s) for 0 argument(s)
Namespace variablesa store to and a read of ns::x against its declared typecannot assign 'string' to 'game::score' declared 'int'
Stores through a referencea T& of a scalar, text, container or math type stores what a T slot takescannot assign 'string' to 'a' declared 'int&'
instanceofthe right side names a class; an operand whose type can hold no object'instanceof' tests a class, and 'Dir' is an enum: compare the value with one of its values (x == Dir::value); 'instanceof Unit' is always false: the operand is 'int', never an object of a class
Writes through a const loop variablea writing method call or a field store through a const range-for variable or structured binding over value elements of a known classcannot call 'hit' on 'm': 'm' is const and 'hit' writes its receiver (line 3)
Reference bindingsa T& binds only a T lvalue; a literal reaches a T& parameter only when the function never writes through it (Value Semantics)'bump' writes through parameter 'n' (line 1); pass a variable
Membersa member the receiver's declared class lacks, a member only a subclass declares included; a method an array, map or string lacks; any member of an int, float, bool or char but same_asno member 'range' in class 'Unit'; no member 'pusj' on 'array<int>' (did you mean 'push'?)
Methods and staticsa method read without a call; a static read through an instance or through Class.name'n' is a static member of class 'C': name it C::n
Field initializersan initializer reads only the fields declared above it; a lambda it creates may name any fieldfield initializer of 'spd' reads 'slices' before its initialization: ...
Map subscriptsthe key against the map's declared scalar key type (a char and its one-character string are one key)Cannot use 'string' as a key of type 'int'
CastsT names a type; the operand is judged when the cast runsunknown type in cast: 'Nope'

Common messages​

MessageMeaning
cannot assign 'string' to 'x' declared 'int' (declared at 8:3)a typed store the table rejects
cannot initialize 'x' declared 'int' with 'float': cast<int>(x) truncates toward zero, math::ifloor(x) rounds downA float into an int slot, at every site: a declaration; a store (cannot assign 'float' to 'x' declared 'int', to field 'n'); a compound assignment; an argument; a return; an element (cannot push into 'array<int>': expected 'int', got 'float', cannot insert into); a store through an int&; a typed range-for variable; an int coroutine's yield (cannot yield 'float' from 'g' declared to return 'int'); an int/float conditional (its type is float).
default value of 'b' names parameter 'a': a default cannot read a parametera default argument that names a parameter of its own list
cannot assign to member 'hp' of a map; store the key as ["hp"]a dot store on a map the checker knows
cannot initialize 'a' declared 'Vec2' with 'null': a 'Vec2' is never null; declare 'shared_ptr<Vec2>' (or var) for a slot that can be emptynull into a class value slot (a declaration, a store, an argument, a return, a field initializer)
class 'Node' holds itself by value (Node.next): a class value is never null; make one link a 'shared_ptr<Node>' (an array or a map of them starts empty)a class reaches itself through value fields or a base (A.b -> B.c -> C.a, Derived : Base -> Base.d); an error in a warn region too
cannot initialize 'd' declared 'Dir' with 'int': cast<Dir>(n) converts an int that is one of its valuesan int or another enum's value into an enum slot; d += 1 and d++ are cannot apply '++' to 'Dir'
cannot initialize 'b' declared 'bool' with 'string': write !x.empty() or an explicit comparisona string, an array or a map into a declared bool slot
fill() cannot store into 'array<int>': expected 'int', got 'string'a fill, resize, assign or array<T>(n, v) value the element type rejects
resize() size must be an int, got 'string'a size that is not an int (assign, reserve alike)
cannot initialize 'c' declared 'char' with 'int'the same at a declaration (char c = 65)
cannot initialize 's' declared 'string' with 'int': stringify it with to_string(x) or `${x}`a string slot takes text or a char, never a number, bool, null or container (a store, a parameter, a return and a field carry the same hint)
cannot initialize 'c' declared 'char' with 'string': a char takes a string of exactly one characterA string literal of another length than one into a char slot: a declaration, a store, an argument, a return, a field, an element or a map key, each with its own lead and the run-time text's reason.
cannot apply '+' to 'string' and 'int': stringify it with to_string(x) or `${x}`A number, bool or null beside a string's +, in either order: the run-time error's text, at load. A template string's splices are text; a char joins as its character.
the format text of 'format' must be a string literal: vformat(fmt, ...) formats a run-time text, and + or a template string joins textformat(s, ...) over a string that is not a literal: only a literal is a format string (print and format)
unexpected '#' before 'xs': JaiScript has no length operator; write xs.size()a parse error: Lua's #xs. Any other # is unexpected '#': it begins only #include, #import and a first-line #! shebang
advance() cannot store the yielded 'string' into 'int'a coroutine handle's advance(v) whose declared yield type v's type does not take (advance() writes the yielded value through its argument; pass a variable for a literal)
'sleep' cannot be called in a parallel bodyA sleep in a parallel_for body, or in a lambda handed to parallel_transform or as parallel_reduce's step (its combine is ordinary code). In a destructor or in hot_reload_migrate it is a warning that it blocks there.
nesting too deep for the host thread's stackthe source nests deeper than the parser or the checker can walk on the host thread's stack (run-time twin)
the result of 'f' is discarded, but 'f' is [[nodiscard]]: use it, or keep it in the placeholder (auto _ = f(...);)an expression statement drops the result of a [[nodiscard]] function, method or host callable ([[nodiscard]])
the result of 'string::to_upper' is discarded: it returns a new value and leaves its argument unchanged, so the statement does nothing; keep the result, or call the in-place method (name.to_upper(...))the same for a library copy of an in-place method (string::, array::, map::filter)
'e.hp' writes to 'e', a copy of the element that is never read afterwards, so the write is lost; iterate with 'auto& e' to change the elementa write into a by-value copy nothing reads again (Lost writes); a parameter's text ends take 'T& p' to change the caller's value, a local's declare 'T& x' to change the original
coroutine 'g' cannot take 'n' by reference: it runs on after the call returns, past the argument's lifetime; take it by value (int n), or pass a shared_ptr to share an objecta parse error: a coroutine parameter declared T&, const T&, auto& or var& (Coroutines)
[[nodiscard]] applies to a function or a methoda parse error: the attribute leads a variable, a field, a constructor or a destructor; [[nodiscard]] function 'f' returns void: there is no result to keep for a void function
redeclaration of 'x' in the same scope (declared at 3:9)A block, a parameter list or one unit's top level declares a variable name twice. Not second declarations: a later run of the unit, another unit, an extern's definition, an inline declaration, a local or structured binding named _ (the C++26 placeholder). A class's fields, or a field and a method: redeclaration of member 'x' in class 'C' (declared at 2:15).
'_' is declared more than once in this scope, so it names none of them: give the variable you use its own namea use of _ where its scope declares the placeholder more than once (auto _ = f(); auto _ = g();); a single _ is an ordinary variable ([[nodiscard]])
use of undeclared identifier 'G'no declaration anywhere in the program; extern if the host provides it
'math' is a namespace, not a value; name one of its members (math::name)A namespace's name read as a value (int spd = math;): a host one (math, time, reflect, crypto, binary, string) or a script's. In a [[warn_mode]] region the run time raises Undefined variable 'math'. A class's name read as a value is its constructor (random among them): a typed slot other than a function refuses it with cannot initialize 'spd' declared 'int' with 'class random'.
field initializer of 'spd' reads 'slices' before its initialization: fields initialize in declaration order; declare 'slices' above 'spd'a field initializer reads its own field or one the class declares below it, bare or through this; a lambda it creates may name any field (Classes)
Unary minus requires numeric operand · Unary plus requires numeric operand · Bitwise NOT requires integer operandThe run-time texts (Arithmetic), at load, where no row takes the operand's declared type: a bool, a string, a container, a function, null, a float or a math value under ~, a class whose chain declares no such operator.
unknown type 'Nope'A declared type (a variable, field, parameter, return, range-for variable, element, key, value or pointee) names no class, enum or type of the program or the host. A bare math name adds ; did you mean 'math::vec2' (using math::vec2;)?. A warning in a unit with a dynamic-path include.
no member 'sqroot' in namespace 'math'A qualified name no unit of the program, earlier run or host registration declares in that namespace (a script's namespace math { ... } adds to math::). For a::b::c the longest prefix naming a namespace is the one named. Declare a member the host registers after load with extern (extern function math::scale;, extern). A warning in a unit with a dynamic-path include.
int has no member 'abs' · Cannot use 'string' as a key of type 'int'The run-time texts (builtin type has no member, key type), at load: a member other than same_as of a known int, float, bool or char; a subscript key a map's declared scalar key type refuses.
cannot initialize 'd' declared 'int' with 'enum Direction': an enum's name is its value table, a map<string,int>; name one of its values (Direction::north)an enum's name read as a value is its value table: a slot that cannot hold a map<string,int> refuses it (var, auto and map<string,int> take it)
no member 'zz' in class 'Vec2'the receiver's class (a value's, a handle's or a reference's) is fully known and has no such field or method: cast<T&> if it lives on a subtype
cannot compare 'int' with 'string' using '==': the types have no comparison (it is always false); convert one operandA comparison between two declared types no conversion or comparison operator relates. != is always true; an ordering raises Invalid operands for < operator. A class operand: the text names the class that declares no comparison operator.
cannot apply '*' to 'string' and 'int' (it raises 'Invalid operands for * operator'); convert one operandAn arithmetic or bitwise operator between two declared types no builtin row takes and no operator of the left operand's class answers. Builtin rows: numbers and chars take + - * / %; a string on either side takes +; ints and chars take & | ^ << >>. A class on the left is named (class 'Gator' declares no operator '*'); a compound names its spelling (cannot apply '*=' to 'int' and 'string').
cannot apply '++' to 'bool'++ or -- on a declared type that is not a number or a char (a script class has no ++). On a slot declared char the int it steps to is the store error cannot assign 'int' to 'c' declared 'char'
cannot compare 'int' with null using '==': 'int' is never null (it is always false); compare with a value of its type, or declare the slot var to hold nullnull against a typed slot that never holds it: int, float, char, bool, string, utf8_string, an array, a map, a math value, an enum or a class value. Not checked: a call's container result, which can be null. Handles, functions and var compare with null.
'fib' expects 1 argument(s), got 2 / argument 1 of 'fib': cannot pass 'string' to 'n' declared 'int'Arity and per-argument checks against a callee the checker sees. A name with overloads in other units or earlier executes is checked against all of them (no overload of 'g' matches this call (2 argument(s))).
'g' is already defined (declared at 1:10)a second function with the same signature; overloads must differ in parameter types or count
'G' is used before its declaration (line 2): top-level code runs in order, so declare it above the use or make the use after it · 'f' is called before its declaration (line 2): ...Top-level code reads a variable, a class or a function this file declares only further down; a function or class body may use them anywhere. A name another unit or an earlier run defined is there. A namespace's top level alike: a bare name it declares further down reaches an enclosing namespace's member or the global first, and is this error when neither exists.
reference variable 'r' must be initialized: a reference names a variable from its declaration ona T& declaration without an initializer; nothing loads
argument 1 of 'bump': cannot bind 'float' to 'x' declared 'int&'a T& parameter binds a variable of exactly T (a class T or a subclass); a const T& parameter also takes what a T parameter takes, bound as a temporary
method 'speak' redefines 'Cat::speak': mark it 'override'a method that redefines a base class method says override (and method 'm' marked as override but no base class method found when there is none)
cast<C>(h) copies the instance - use cast<C&>(h) to alias it or cast<shared_ptr<C>>(h) to share ita warning: the cast is legal, but probably not what you meant
map keys of class 'C' compare by identity: declare operator<=> (or operator<) or hash() to key its values by valuea warning, from the checker at the subscript and once per class from the run time: a value of C keys a map by identity
No bound 'int * Meter': bind operator "*" as (int, Meter) on Meter, or convert the operanda warning: a number on the left of a bound class's arithmetic operator the class binds no reflected form of
'f' declared to return 'int' may reach the end of its body without returninga primitive, string, enum, class value or reference return is required on every path
'heal' is a method of Player; call it with p.heal() or bind it with reflect::bind(p, "heal")a method read without a call
to_upper changes name in place and returns nothing; string::to_upper(name) returns an uppercased copyA call uses the result of an in-place builtin on a known array, map, string or handle (run-time twin).
'bump' writes through parameter 'x' (line 1); pass a variablea literal or temporary passed to a T& parameter the body writes through
argument 3 of 'parallel_reduce': step 'one' must take two parameters (acc, x)a declared step or combine of another arity (argument 4 ... combine ... (a, b) alike)
cannot bind a reference to a conditional of 'int' and 'float': its arms must have one typea T& argument, declaration, default, return or cast<T&> over a conditional whose arms name storage of two types (one arm type binds the chosen variable)
cannot bind non-lvalue default to reference parameter 'p'a T& parameter's default that can never name storage (int& p = 5); a const T& one binds a temporary, and a coroutine binds a copy
cannot assign to a call result: 'get' returns by value · cannot assign to x++: it yields the old value · cannot assign to a literalan assignment target that names no storage (the runtime texts below, lowercased)
regex: missing ')' to close the group at position 1a regex(...) whose literal pattern or flags do not compile; the text is the run time's (Regular expressions)
'x' is already defined inline; declare it 'inline int x;' to share ita plain declaration of an inline variable another unit shares
argument 1 of 'run_sql' is not a constant: <the host's refusal>an argument the host declared constant (constant arguments) is not a literal, a const of one, or a ternary, + or array literal of them
the format text of 'print' has 2 placeholder(s) for 1 argument(s)a print or format literal whose placeholders and arguments do not pair up (also names {2}, past its 1 argument(s) and never uses argument 1 of its 2 argument(s))
'to_string' expects 0 argument(s), got 1: the method hides the function 'to_string' here; call that one as ::to_string(...)a bare call in a method finds the class's member first; the member refuses the arguments and the function it hides takes them
push changes a call result in place and nothing reads it: 'a.list' returns by valueAn in-place builtin called on an array, a map or a string a script function returns by value. An element store into one: cannot assign to a call result: 'a.list' returns by value.
'n' is a static member of class 'C': name it C::nA static read, stored or called through an instance (c.n, this.n, c.bump()). A method's bare n or C::n names it.

Run-time errors (what catch sees)​

jaiscript
var dynamic = "hello";        // var: the checker cannot see what it holds
try {
    int x = dynamic;          // so this fails at run time, where catch sees it
} catch (e) {
    print("caught: {}", e);
}
output
caught: Cannot initialize 'x' (declared int) with string

Run-time texts lead with the action that failed, or with the builtin or member that refused it; names are quoted. catch (e) receives an error that reads as the text alone. An uncaught error's what() on the host side is the same text alone, with no category or location appended (only an error raised without a text of its own reads as its category's name). Every text is byte-identical on both backends.

Error kinds​

A caught error's e.kind is one of the error_kind:: names (each is a string holding its own name), decided by the error's code, so a script tells errors apart without reading their text:

KindErrors
error_kind::null_receivera member read or a call through null
error_kind::no_membera member or static member the value does not have
error_kind::namean undefined variable or class
error_kind::not_callablea call of a value that is not a function
error_kind::argumentsan argument count, a constructor or an overload that does not match, an ambiguous call
error_kind::typea typed slot, parameter, return, element, key or cast that refuses the value
error_kind::arithmeticinteger overflow, division or modulo by zero, a non-numeric operand
error_kind::boundsan array or string index out of range
error_kind::key_not_founda read of a map key that is not there
error_kind::containeran element taken from an empty array
error_kind::referencea reference, handle or capture that cannot bind
error_kind::limitthe call-depth cap, the memory cap's first raise
error_kind::hostan exception a C++ function raised: a host function or a library builtin
error_kind::otherevery other run-time error

The catalog, by family:

Null receiver​

TextWhenFix
Cannot access 'x' on null ('v' is null)Member read through a null variable.Null-check, or assign an object.
Cannot call 'push' on null ('v' is null)Method call through a null variable.Null-check, or assign an object.
Cannot call 'x' on null ('f(...)' returned null)Method call on a null call result.Null-check the result.
Cannot access 'x' on nullMember read through an unnamed null receiver.Null-check the receiver.

No such member​

TextWhenFix
Vec2 has no member 'x'Neither the class nor its bases declare the name.Fix the name, or declare the member.
int has no member 'foo'No such method on the builtin type; all read alike (string has no member 'foo'). Load error where the checker knows the receiver is an int, float, bool or char.Use a listed method (Builtin methods).
map has no member 'foo'; read the key as ["foo"]Dot access names no map method. Keys use []; only enum values use a dot (Direction.north). Load error where the checker sees a map.Write m["foo"], or fix the method name.
map has no member or key 'foo'Dot access on an enum value table, where the checker cannot see the enum, names neither a map method nor a value.Fix the value name.
parent class Base has no member 'x'super::name names nothing the base declares.Name a base member.
class C has no static member 's'C::s names no static of the class or its bases.Declare the static, or fix the name.
Cannot call 'helper' while 'A' is under construction: only a class derived from it declares itConstructor or field initializer calls what only a derived class declares.Declare it in this class, or call after construction.
Cannot call 'helper' while 'A' is under destruction: only a class derived from it declares itDestructor calls what only a derived class declares.Declare it in this class, or do the work in the derived destructor.
Cannot assign to 'x': Vec2 has no such memberStore to an undeclared member.Declare the field, or fix the name.
Cannot assign to member of non-object typeMember store through null or a primitive.Assign an object first, or null-check.
'C' is a class; use C::sDot after a class name.Write a static as C::s.
No value 'v' in enum 'E'E::v names no value of the enum.Use a declared value.

Not a function​

TextWhenFix
Cannot call 'x': it is an int, not a functionCalled variable holds a non-function.Call a function, or rename the variable hiding it.
Cannot call 'f': it is null, not a functionCalled variable holds null.Assign a function or lambda first.
Cannot call a value of type int: it is not a functionComputed callee (an element, a call result) is not a function.Call only functions.
Cannot call null: it is not a functionComputed callee is null.Null-check first.

Arity and overloads​

TextWhenFix
'fib' expects 1 argument, got 2Call passes more or fewer arguments than declared.Pass the declared count, or add parameter defaults.
lambda expects 1 argument, got 0Lambda gets more or fewer arguments than declared.Pass the declared count.
No overload of 'dot' takes (int, string)No overload accepts the argument types.Match an overload, or declare one.
No constructor of 'Vec2' takes (string)No constructor accepts the arguments.Match a constructor, or declare one.
No constructor found for class 'X'new X() where X names no class.Define or import the class, or fix the name.
Ambiguous call to 'hit' with (int, int): 'hit(int, float)' and 'hit(float, int)' match equallyTwo overloads match equally.Convert an argument (cast<float>(x)) so one wins.
'f(var& x)' differs from 'f(var x)' (line 1) only by reference; overloads must differ in parameter types or countTwo overloads differ only by reference; the text names the second definition, then the line of the first.Differ in parameter types or count, or keep one.
Too many initializers for 'Bare': it has 1 field, got 2Aggregate initialization passes more values than fields.Pass at most one value per field.
Base 'Cat' has no default constructor; call super(...)Constructor omits super(...); the base has no default constructor.Add : super(args).
Class 'Car' must construct base 'Radio': it has no default constructorInitializer list omits a later base with no default constructor.Name that base with its arguments.
Class 'Car' has no base 'Wheel' to constructInitializer list names a non-base class.Construct only own bases.
Class 'Car' constructs base 'Engine' twiceInitializer list names a base twice.Construct each base once.
No matching parent constructor found for super()super(...) passes arguments; the base declares no constructor.Drop the arguments, or declare a base constructor.
push() takes exactly one argumentWrong argument count to a builtin method; all read NAME() takes ....See Builtin methods.
size() takes no argumentsArguments to a builtin method that takes none.Pass none.
remove() argument must be an integerWrong argument type to a builtin method; all read NAME() argument must be ....Pass the listed type.
math::wrap expects 3 argumentsWrong argument count to a math function; all read math::NAME expects ....See the API signatures.
math::sqrt expects a numeric argumentNon-number to a math function.Pass an int or a float.

The typed boundary​

TextWhenFix
Cannot pass string to parameter 'n' of 'fib' (declared int)Argument does not convert to its typed parameter.Pass the declared type, or convert.
Cannot return string from 'f' (declared -> int)Returned value does not fit the declared return type.Return that type, or change the declaration.
Cannot assign string to 'x' (declared int)Other type stored into a typed variable. A shared_ptr<T> takes a handle to T or a derived class, never a weak_ptr; a weak_ptr<T> keeps T through every store.Assign the declared type, convert (weak.lock() for a shared_ptr), or declare var.
Cannot initialize 'x' (declared int) with stringTyped declaration initialized with another type.Use the declared type, or convert.
Cannot assign string to field 'f' of C (declared int)Other type stored into a typed field.Assign the declared type.
Cannot assign string to static 's' of C (declared int)Other type stored into a typed static.Assign the declared type.
Cannot convert B to A (no suitable single-argument constructor)B object reaches a slot typed A; A has no constructor taking a B.Pass an A, or add that constructor.
Cannot store string in array<int>Other element type stored into a typed array.Store the element type.
Cannot initialize 'r' (declared float&) with intTyped reference binds another type.Bind a variable of that type, or declare auto&.
Cannot yield string from 'g' (declared -> int)Coroutine yields a value its declared type does not take.Yield the declared type.
Cannot initialize 'w' (declared weak_ptr<Foo>) with Fooweak_ptr initialized from a value, not a handle.Use a shared_ptr<Foo>.
Cannot pass string to an int parameterParameter type check fails with no parameter name known.Pass the declared type.

Numeric conversion​

TextWhenFix
Cannot convert float to integer: non-finite or out of rangeNaN, infinity or a float outside the int64 range reaches cast<int>, math::itrunc or math::ifloor; the destination is not written.Check finite and in range first.
Cannot store 256 in array<uint8> (0..255)array<uint8> store outside 0..255.Stay in range, or mask with & 255.
Cannot store -129 in array<int8> (-128..127)array<int8> store outside -128..127.Stay in range.

Containers​

TextWhenFix
Cannot push 'string' to array<int>push, resize, assign, fill or array<T>(n, v) adds another type to a typed array.Use the element type.
array size cannot be negativearray<T>(n), resize, assign or reserve gets a size below 0.Pass 0 or more.
resize() size must be an intresize (assign, reserve alike) gets a non-int size.Pass an int (cast<int> a float).
Cannot assign 'string' to element of type 'int'Other type stored into an element.Store the element type.
Cannot use 'int' as a key of type 'string'Other key type on a typed map. Load error for a subscript whose key and declared key type the checker knows.Use the declared key type.
hash() of a map key must return an intClass keying a map through hash() returns a non-int from it.Return an int.
Array 'auto' requires homogeneous elements - type mismatch at index 3auto array literal mixes element types.Use one type, or declare var or array<var>.
Map 'auto' requires homogeneous valuesauto map literal mixes value types.Use one type, or declare var values.
Cannot iterate int: not an array, map, string or coroutineRange-for over a non-iterable value.Iterate one of the listed types.
Cannot bind array to [k, v]: a structured binding takes a map entry or a value with first and secondStructured binding gets neither a map entry nor a value with first and second.Bind a map entry; destructure an array with auto [a, b] = arr.
map() requires a function argumentmap() gets a non-function.Pass a function or lambda.
Cannot insert 'string' into array<int>insert adds another type to a typed array.Use the element type.
Cannot insert at index 9 of an array of size 5insert index past the end.Use 0 to size().
Cannot reduce an empty array without an initial valuereduce on an empty array with no initial value.Pass an initial value.
Destructuring requires an array on the right-hand sideauto [a, b] = value gets a non-array.Destructure an array.

Handles and references​

TextWhenFix
reset(h) takes a handle (new T(), make_shared<T>() or a shared_ptr), not Cp.reset(h) where h is a value or a primitive (load error when the checker sees it).Pass a handle (p.reset(new C())), or assign into the object (p = C()).
Cannot reset shared_ptr<C> to a shared_ptr<U>p.reset(h) where the class of h is neither that of p (for a var, of the held object) nor a subclass.Reset to a handle of that class or a derived one.
reset() takes at most one argumentshared_ptr reset gets two or more arguments; on a weak_ptr any argument raises reset() takes no arguments.Call reset() or reset(h).
Cannot initialize shared_ptr directly from weak_ptrshared_ptr initialized from a weak_ptr.Use weak.lock().
Cannot create weak_ptr from value-semantic object. Use shared_ptr<T>.weak_ptr<T>(v) of a value.Make the object with new; take the weak_ptr from its handle.
Cannot pass non-lvalue to reference parameterTemporary (a literal, a by-value call result) reaches a & parameter that needs a variable, unrejected at load: one the function writes through, or any reference parameter of a lambda called through a variable. A & parameter only read binds a temporary (Value Semantics). A call returning T& (script function or host) is an lvalue and binds.Pass a variable holding the value.
Cannot bind non-lvalue default to reference parameter 'p'Reference parameter default names no storage; raised at the call using the default.Pass an argument, or default to a variable.
Cannot take reference of non-lvalue expression (...)Non-const reference binds an expression naming no storage; the parenthesis lists what a reference binds.Bind a variable, field or element, or declare const T&, which holds a temporary while the reference lives.
Function with reference return type must return an lvalue referenceT& function returns an expression naming no storage: a temporary, a by-value call result, a map key with no entry (a read never inserts).Return a variable, field, element or existing entry, or return by value.
Cannot take reference of undefined variableReference names a nonexistent variable.Declare it first, or fix the name.
Reference variable must be initializedReference declared without an initializer (int& r;).Initialize with a variable, field or element.
Reference to a removed array elementElement reference used after the array shrank past it (pop, erase, clear). The reference names an index: after an insert or reorder it names the element then at that index.Rebind after shrinking, or keep the index.
Reference to a removed fieldField reference used after a hot reload removed the field from the class.Rebind after the reload.
Reference target is nullReference binds, or is read through, a reference with no target.Bind a live variable, field or element.
Reference to a removed map entryReference used after its map entry was erased (array element and field alike).Rebind after the removal, or keep the entry.
Cannot iterate a string by reference: its chars are not lvalues (use for (auto c : s))for (auto& c : s) over a string.Use for (auto c : s).
A host function returning std::weak_ptr<T> is not supported; return shared_ptr<T>Script calls a host function bound to return std::weak_ptr<T>.Return shared_ptr<T> from it.
Cannot assign to a reference to 'C': its binding has no operator=Assignment through a reference to a host object whose binding lacks "=".Bind "=" on the host side, or assign fields one by one.

Const​

TextWhenFix
Cannot assign to 'MAX': it is read-onlyStore to a const variable.Drop const, or store into a copy.
Cannot assign to 'p.x': it is read-only ('p' is const)Field store through a const object.Drop const, or use a non-const copy.
Cannot call 'bump' on 'c': 'c' is const and 'bump' writes its receiver (line 5)Field-writing method called on a const object.Drop const, or use a non-const copy.
Cannot call 'push' on 'xs': 'xs' is const and 'push' changes itContainer-changing builtin method called on a const one: listed as mutate in the API reference, or handing elements to a callback that writes through the & parameter an element binds (for_each, find, reduce, ...).Drop const, or use a non-const copy.
Cannot bind 'r' (declared int&) to const 'a'; declare it const int& or auto&Non-const reference binds a const variable.Declare const int& or auto&.
Cannot pass const 'a' to parameter 'x' of 'inc': 'inc' writes through it (line 1)const variable passed to a reference parameter the function writes.Pass a non-const copy, or stop writing the parameter.
Cannot cast const 'a' to int&: cast<int>(a) copies itReference cast of a const variable.Copy with cast<int>(a).
Cannot share const 'p' as shared_ptr<P>; copy it into a variable firstconst value shared where a shared_ptr<P> is wanted.Share a non-const copy.
Cannot return const 'a' from 'f' by reference (declared -> int&); return it by valueReference-returning function returns a const variable.Return by value.

Assignment targets​

TextWhenFix
Cannot assign to a literalAssignment to a literal.Assign to a variable, field or element.
Cannot assign to an array literalAssignment to an array literal (a map literal alike).Assign to a variable, or destructure: auto [a, b] = arr.
Cannot assign to a call result: 'get' returns by valueStore to the result of a by-value function.Return -> T&, or store into a variable.
Cannot assign to x++: it yields the old valueStore to a postfix increment or decrement.Assign to the variable.
Cannot assign to the result of '+': it is a temporary valueStore to an operator result.Store into a variable.
Cannot assign to the result of cast<float>(x): it is a temporary value (cast<float&>(x) names the variable)Store to a value cast.Store through cast<float&>(x).
Cannot assign to 'x': it is read-onlyStore to a getter-only host property or a host namespace entry.Use the host setter, or keep the value in a script variable.
Cannot assign to a conditional: its arm '5' names no storageStore to c ? a : b with an arm that is not a variable, field or element.Make both arms name storage, or assign in an if.
Cannot assign to 'this'Store to this.Assign fields one by one.
Cannot assign to this expression: it names no storageTarget names no variable, field or element.Assign to a variable, field or element.
Cannot assign to rvalue expressionStore, compound assignment or ++ on an element of a temporary.Store the temporary in a variable first.
Cannot assign to a member of a temporarymake().x = 1 on a class or math value returned by value, a constructor call or an operator result.Store the value in a variable first.

Methods as values​

TextWhenFix
'heal' is a method of Player; call it with player.heal() or bind it with reflect::bind(player, "heal")Script method used as a value, not called.Call it, or use reflect::bind.
'push' is a method of array; call it with arr.push() or wrap the call in a lambdaBuiltin method used as a value, not called.Call it, or wrap the call in a lambda.
filter changes xs in place and returns nothing; array::filter(xs, f) returns a filtered copyResult used of a builtin method that changes its receiver in place and returns nothing (auto ys = xs.filter(f), xs.filter(f).map(g)); on a var, raised when the call runs, before any change. The copying twin follows when there is one (In place or a copy). A parallel worker that never saw the text says filter changes its receiver in place and returns nothing.Call it as a statement, or call the twin.

Casts​

TextWhenFix
Cannot cast 'X' to 'T'cast<T> of a value that does not convert to T.Cast between convertible types.
Cannot cast 'int' to 'char'cast<char> of an int outside 0..255.Cast 0 to 255.
Cannot cast 'null' to 'T&'Reference cast of null.Null-check first.
Cannot cast 3 to 'E': not one of its valuescast<E> of an int that is no value of the enum.Cast a declared value.

Names​

TextWhenFix
Undefined variable 'x'Name the checker could not rule on (var-typed paths, dynamic imports) names nothing at run time; or top-level code reads a global, constructs a class or takes a function as a value before its declaration (top-level order).Declare the name, or fix its spelling.
'x' is declared extern but never defined (an 'inline' declaration creates it)Used extern variable (a qualified one too: the text names 'game::tick') has no definition.Define it, have the host register it, or declare it inline.
'f' is declared extern but never definedUsed extern function f; (or extern function ns::f;) has no definition.Define it, or have the host register it.
'x' is already defined inline; declare it 'inline int x;' to share itPlain definition meets an inline one of the same name.Declare it inline too.
'x' is already defined (not inline) in <file>; declare every definition 'inline' to share itinline definition meets a plain one in another file.Declare every definition inline.
Undefined variable 'x' (not a field of 'this')Name in a method is no local, field of the class or global.Declare the name, or fix its spelling.
Class 'C' not foundRun-time class name names no defined class.Define or import the class, or fix the name.
reflect::construct: unknown class 'Nope'reflect::construct gets a non-class name.Pass a defined class name.
Cannot capture undefined variable 'x'Capture list names a nonexistent variable.Declare it first, or fix the name.
Lambda capture list does not capture enclosing name 'v'; name it, or use [this], [=] or [&]Lambda body uses an enclosing local missing from its capture list.Name it there, or use [this], [=] or [&].
Namespace 'jai' is reserved for the engine (C++-registered only)Script declares into the jai namespace.Use another namespace.
'this' can only be used inside methodsthis outside a method.Use it only in methods, constructors and destructors.
Cannot call super() - class has no base classsuper(...) in a class with no base.Remove the call, or add a base.

Definitions​

At load the strict checker reports the class texts, and the method texts with a lowercase first letter.

TextWhenFix
Base class 'X' not foundBase name is not a defined class.Define or import the base first, or correct the name.
Class 'D' inherits 'A' through both 'B' and 'C' (diamond inheritance is not supported)One base reached through two paths.Give each base one path.
Method 'm' marked as override but no base class method foundoverride method overrides nothing.Remove override, or use a base method name.
Method 'm' redefines 'Base::m': mark it 'override'Base method redefined without override.Mark it override, or rename it.
'g(int a)' is already defined (line 1)Signature defined twice in one run of one program text; another execute or a re-run unit replaces it instead.Rename one, or change its parameters.
Function 'f' already exists in namespace 'ns'. Use 'override' keyword to replace it.Namespace function of an existing signature defined again without override.Rename one, or mark the replacement override.
'f' is already defined with parameters ()Same-file namespace reopening redefines one of its functions; the strict checker reports it at load.Define it once, or rename one.

Arithmetic​

TextWhenFix
Integer overflow in '+'Int result outside int64 ('-', '*', '/', unary '-' alike), an atomic<int>'s fetch_add and fetch_sub included.Use smaller values or a float; math::wrap_add wraps on purpose.
Integer overflow in '+='Compound assignment int result outside int64, on any target (variable, field, element, map entry, atomic<int>); '-=', '*=', '/=' alike.Use smaller values or a float; math::wrap_add wraps on purpose.
Integer overflow in '++'++ steps an int past int64 ('--' below it), on any target, atomic<int> included.Check the bound first, or step a float.
Bitwise & requires integer operands& operand is not an int or char (|, ^ alike) and no class operator takes it; at load when both operand types are known.Convert the operands to int (cast<int>).
Left shift requires integer operands<< operand is not an int or char and no class operator takes it; at load when both operand types are known.Convert the operands to int.
Right shift requires integer operands>> operand is not an int or char and no class operator takes it; at load when both operand types are known.Convert the operands to int.
Bitwise NOT requires integer operand~ operand is not an int or char (a char promotes to its int) and no class operator takes it; at load when its type is known.Convert the operand to int.
Unary minus requires numeric operandUnary - operand is not a number, char (promotes to its int) or math value and no class operator takes it; at load when its type is known (-true).Negate an int or a float.
Unary plus requires numeric operandUnary + operand is not a number, char (promotes to its int) or math value (returned as a copy) and no class operator takes it; at load when its type is known.Apply it to an int, float, char or math value.
Division by zero/ or /= divides an int by an int zero (a float operand gives an IEEE infinity or NaN).Check the divisor first.
Modulo by zero% or %= of two ints takes a zero divisor.Check the divisor first.
Shift amount must be between 0 and 63Shift count negative or above 63.Keep the count from 0 to 63.
Cannot apply '+=' to int and stringCompound assignment has no rule for its operand types (every compound and destination); at load when both types are known (cannot apply '+=' to 'int' and 'bool').Convert an operand so the types match.
Cannot apply '++' to string++ or -- targets a value that is not a number or char, or an object whose class binds no ++ of that form; at load when its type is known.Increment an int, float or char (promotes to its int); a C++ class binds operator++() as [](T&) and operator++(int) as [](T&, int64_t).
Cannot convert 'string' to 'char': a char takes a string of exactly one characterString of a length other than one reaches a char slot: variable, parameter, field, return, array<char> element or map<char, V> key. A literal fails the load with the same reason (as a subscript key, with this text).Index the character (s[0]), or keep the slot a string.
cannot apply '+' to 'string' and 'int': stringify it with to_string(x) or `${x}`Number, bool or null beside a string under +, either order (the text names both types); the same text at load when both types are known.Make the other side text: to_string(x), or a template string `${x}` (splices are text).
Invalid operands for + operator+ has no rule for its operand types and no user operator+ takes them (-, *, /, % alike: numbers and chars take every one; a string on either side takes +). At load when both operand types are known.Convert an operand, or declare the operator in the class.
No bound 'Money + int': bind operator "+" taking int on Money, or convert the operandBound C++ class declares the operator, but no bound overload takes the other operand.Bind an overload taking that type, or convert the operand.
No bound 'int - Money': bind operator "-" as (int, Money) on Money, or convert the operandNumber or other non-class value left of a bound class operator, and the class binds no reflected form taking it (for a comparison the text asks for "<=>" taking int on Money).Bind the reflected form, .method("-", [](int64_t l, const Money& r) { ... }), or convert the operand.
Invalid operands for < operator< compares types with no ordering, and no user operator takes them.Compare values of one comparable type, or declare the operator in the class.

Vectors​

TextWhenFix
math::vec3 expects one vector of 3 componentsOne-argument vector constructor gets a lone scalar or a vector of another dimension.Pass a same-dimension vector, or every component.
math::color expects one colorOne-argument math::color gets a non-color.Pass a color, or every component.
math::vec4 expects a narrower vector followed by scalars that complete 4 componentsWrong number of scalars after a narrower vector.Follow the vector with exactly the missing components.
math::vec2 expects numeric componentsVector constructor component is not a number.Pass ints or floats.
math::vec3 expects 0 to 3 argumentsToo many constructor arguments (every vector type, named by its own type and count).Pass at most one argument per component.
Integer overflow: the value does not fit an int32 componentInt for an ivec2 or ivec3 component (constructor, component store, arithmetic result, loaded archive) outside int32. A JAISCRIPT_WRAP_ON_OVERFLOW build wraps it instead.Keep components within int32, or use a float vector.

Indexing​

TextWhenFix
Array index 5 out of bounds for array of size 3Array index negative or not below size().Index from 0 to size() - 1.
Key "helth" not found in mapSubscript reads a key the map lacks (typed and var maps alike): a plain read, a compound assignment or increment (reads first), ?? or ??= on the entry, a reference bound to it, or a chain link such as m[a][b]. The key shows as inside a container: string or char quoted, number plain. In a parallel body, a key whose text the program never made shows as Key not found in map.Ask contains(k) first, or read with get(k) (null) or get(k, fallback); m[k] = v inserts.
Array index must be an integerArray subscript is not an int.Index with an int (cast<int> a float).
String index 4 out of bounds for string of size 4String index negative or not below size().Index from 0 to size() - 1.
Subscript can only be used on arrays, maps, or types with [] operator[] on a value that is no container and declares no operator[].Subscript a container, or declare operator[] in the class.
Cannot pop from empty arraypop on an empty array.Check size() first.
Cannot get front of empty arrayfront on an empty array (back alike).Check size() first.
front() called on empty stringfront() on an empty string (back() alike).Check size() first.
String index must be an integerString subscript is not an int.Index with an int.
Cannot assign int to a string character (it takes a char or a string)String element store of a value that is neither a char nor a string.Store a char (cast<char>(n)) or a string.

Strings, bytes, time​

TextWhenFix
code() needs a string of exactly one UTF-8 charactercode() on a string that is empty or holds more than one character.Call it on a one-character string.
to_char expects 0..255, got 300to_char gets an int outside 0..255.Pass an int from 0 to 255.
string::repeat count cannot be negativestring::repeat gets a negative count.Pass a count of 0 or more.
Unsupported format spec ':q' in format stringformat() or print placeholder {:spec} / {n:spec} names a spec outside the subset (a template string ${x:q} is the load-time Unsupported format spec ':q' in template string).Use the subset, [[fill]align][+| ][0][width][,|_][.precision][d|x|X|b|f|e|g]; write {{ for a literal brace.
Format text has 2 placeholder(s) for 1 argument(s)Placeholders and arguments do not pair up: the {} count differs from the argument count; a {n} names none (Format text names {2}, past its 1 argument(s)); no placeholder takes one (Format text never uses argument 1 of its 2 argument(s)). A literal mismatch fails the load; one in vformat raises.Pair every placeholder with an argument; text without a placeholder joins its arguments.
format spec ':.2f' does not apply to string valueSpec sign, zero padding, grouping, precision or type does not fit the value (a string under a numeric spec, a float under x).Pass a value of the kind the spec formats, or convert it first.
to_bytes(4) out of bounds for string of size 3to_bytes offset or count past the end of the string.Keep offset and count within size().
string::from_bytes expects bytes (0 to 255): element 3 is 256string::from_bytes element outside 0..255.Pass bytes from 0 to 255.
Cannot read int32 at position 10: 4 bytes wanted, 2 remainBinary reader reads past the end of its data.Check the bytes remaining first.
Cannot write 256 as uint8 (0 to 255)Binary writer value outside the range of its width.Write values in range, or use a wider width.
Cannot read null-terminated text at position 0: no NUL terminator in the remaining 3 bytesReader text() finds no NUL before the end of its data, or before the engine binary scan limit (the text then names the limit).Read a counted field with text(n), or check the data holds a terminator.
Cannot write text: the text holds a NUL at byte 1Writer text(s) gets a text with a NUL inside. text(s, n): Cannot write text: the text is 6 bytes, longer than text(3) for a text longer than its field; Cannot write text(s, -1): a count cannot be negative for a negative count.Remove the NUL, or give the field room for the text.
Cannot pack field 'pos': the map has no 'pos'Layout packs a map lacking one of its fields.Give the map every field the layout names.
binary::layout expects name, width pairs, got 3 argumentsbinary::layout gets an odd number of arguments (reader, writer and layout texts in full: Binary data).Pass a name and a width per field.
time::date: month must be 1 to 12, got 13time::date month outside 1..12.Pass a month from 1 to 12.
web::url_encode expects a stringweb:: function argument is not text (every one reads web::NAME expects a string; web::build_query expects a map).Pass the kind the web:: library names.
web::build_query: the value of 'm' is a mapweb::build_query value is neither text, a number, a bool, null nor an array of those (... is an array holding more than text, numbers and bools, ... is not text, a number, a bool or an array of them).Pass text, numbers and bools, or an array of them.
web::parse_url: 'http://example.org:99999/' has a malformed host or portPort is not a number from 0 to 65535, or an IPv6 host bracket does not close.Correct the URL, or catch the error for outside input.
spider::catch: no HTTP transport installed: the host provides one with engine::http_transport()spider:: call in an engine whose host registered the client and installed no transport (every call reads spider::NAME: ...).Install one with engine::http_transport.
spider::catch: http://127.0.0.1:1/: cannot connect to 127.0.0.1:1Exchange failed: the transport reason, or timed out after N s, more than N redirects, a redirect from https to http (URL) is refused, redirected to 'L', which is not an http or https URL.Catch it; raise the timeout or redirects option for a slow or far server.
spider::catch: 'ftp://example.org/' is not an http or https URLURL is relative, of another scheme, or has no host.Pass an absolute http or https URL.
spider::catch: unknown option 'retries' (method, headers, timeout, type, redirects)Option unknown or of the wrong kind (option 'method' takes GET, HEAD, POST, PUT, PATCH, DELETE or OPTIONS, option 'timeout' takes a number of seconds above 0, option 'redirects' takes an int from 0 to 100, 'N' is not a header name, header 'N' holds a line break or NUL in its value, header 'Host' is the transport's to set (Content-Length, Transfer-Encoding and Connection too), type "form" takes a map of fields).Use the options HTTP with spider:: lists.
Response.header: 'X Y' is not a header name, or its value holds a line break or NULspider::Response.header(name, value) gets a name that is not an HTTP token, or a value holding CR, LF or NUL.Use a token name (letters, digits and !#$%&'*+-.^_`|~) and a one-line value.
time::date::add_days expects a whole numberCalendar step (add_days, add_months, add_years) gets a fraction, an infinity or NaN.Pass a whole number.
time::date::add_days is out of rangeCalendar step or duration in add_* past ±1015 (days, months, years, or a duration in milliseconds).Step by a smaller amount.
time::date::format: unknown placeholder '${bogus}'Date format string names an unknown placeholder.Use a placeholder from Time.

Regular expressions​

TextWhenFix
regex: missing ')' to close the group at position 0Pattern does not parse; every such text reads regex: PROBLEM at position N, N counting characters from 0 (the texts in full: The syntax).Correct the pattern at that position.
regex: the backreference '\1' at position 3 is not supported: matching runs in linear time, without backtrackingPattern uses a construct that needs backtracking: a backreference, a lookahead or lookbehind, an atomic group, a possessive quantifier or recursion, each named alike.Match more and test the parts in script, or capture and compare the groups.
regex: unknown flag 'g' (the flags are i, m, s and x)Flags hold a letter that names no flag (regex: flag 'i' appears twice for one written twice).Pass only i, m, s and x (find_all and replace cover every match).
regex: the class at position 0 holds 'é', a character of more than one byte, but a string matches by bytes (match a utf8_string, or write its bytes as \xNN)Pattern whose class holds a multi-byte character searches a string.Search a utf8_string, or name the bytes with \xNN.
regex: the pattern is too large to match a string (its program passes 250000 instructions)Counts multiply past the engine program limit ((a{1000}){1000}).Use smaller counts, or a loop in script.
regex: the replacement names group 2 at position 0, but the pattern has 1 groupReplacement refers to a group the pattern lacks (regex: the replacement names group 'x' at position 0, which the pattern does not have by name; regex: a '$' at position 1 of the replacement starts no group reference (write $$ for a dollar sign) for a stray $).Refer to a group the pattern has; write $$ for a dollar sign.
regex: the replace function must return a string, got intFunction replacement returns a non-text value.Return a string (to_string(v)).
regex::match has no group 5 (it has 4 groups)Match asked for a group past its last (regex::match has no group named 'day' for an unknown name).Ask for group 0 to m.size() - 1, or a name the pattern gives.
regex: search position 4 is outside the text (0 to 3)search(text, start) start before 0 or past the end.Start between 0 and the size of the text.
regex: search expects a string or utf8_string, got intRegex call searches a non-text value (regex: the pattern must be a string, got int for the pattern).Pass a string or a utf8_string.

Random numbers and crypto​

TextWhenFix
random::next_int range is inverted (max < min)next_int(lo, hi) gets hi below lo (random::next_float range is inverted (max < min) for floats).Pass the bounds low first.
random::next_float bounds must be finitenext_float(lo, hi) gets an infinite or NaN bound.Pass finite bounds.
random::pick expects a non-empty arraypick gets an empty array or a value that is no array.Check the array size first.
random::shuffle expects an arrayshuffle gets a value that is no array.Pass an array variable.
random::next_bytes count cannot be negativenext_bytes (or crypto::random_bytes, crypto::random_hex: crypto::random_bytes count cannot be negative) gets a negative count.Pass a count of 0 or more.
random::state expects 64 hex digits, not all zeroStore into state (a load included) is not 64 hex digits, or is all zeros.Store a value read from state.
crypto::random_int range is inverted (max < min)crypto::random_int(lo, hi) gets hi below lo.Pass the bounds low first.
crypto::random_bytes: the operating system's secure random generator failedSystem generator refused to answer (the text names the function: random_hex, random_int, password_hash, or random: ... for random()).Retry; the platform entropy source is unavailable.
crypto::password_hash cost must be 4 to 31password_hash cost outside 4..31.Pass a cost from 4 to 31 (12 by default).
crypto::password_hash: the password contains a NUL bytePassword holds a 0 byte, which bcrypt cannot read past.Reject or encode such passwords before hashing.

Templates​

Errors marked at load fail the script that calls template before it runs, as a parse failure listing the template file and line. A scoped template's rules about its text fail at load for a literal text or path, at the first render otherwise (HTML Templates). A template file read with the filesystem privilege off raises Insufficient privilege: filesystem. where the call renders.

TextWhenFix
template() argument 2 is not a plain variable name: the template sees each argument by its name, so name the value first (auto entry = rows[0];) and pass the nametemplate argument after the path is not a plain name (at load).Name the value in a local and pass the local.
template() takes a path, then the names the template seestemplate() called with no arguments (at load).Pass the template path first.
template() path is not a stringPath known at run time is not text.Pass the path as a string.
scoped_template(path, map) takes 2 arguments, got 1scoped_template or scoped_template_text gets another count of arguments (at load).Pass the path or the text, then the map.
raw() takes 1 argumentraw in a template gets another count of arguments.Pass the one value to splice unescaped.
template() names 'entry' twiceOne name passed twice (at load).Pass each name once.
template file 'page.spider' not foundPath resolves to no file (at load for a literal path, at the render otherwise; ... cannot be read when the file cannot be opened).Check the path: it resolves from the calling script file, as an import path does.
a template sees only the names passed to it and the program's names; 'this' is not one of them (pass a local instead)Template names this or super (at load).Pass the value the template needs as a name.
a lambda in a template captures 'total', which the template does not seeLambda in a template captures a name the template was not given (at load).Pass the name to the template.
unexpected text after the template bodySplice ends the body early, such as ${::g}, whose : starts a format spec.Parenthesize the expression: ${(::g)}.
a template splice is null: ${title} at page.spider:3Splice in a template or a scoped template evaluates to null (at load for a literal null).Give the value, or write ${title ?? ""}.
Insufficient privilege: scoped_template.scoped_template or scoped_template_text on an engine whose host disabled jai::scoped_template.The host enables jai::scoped_template.
scoped_template: '../secret.txt' names a parent directory (..)Scoped template path has a .. segment.Name the file from inside a template folder.
scoped_template: 'C:/secret.txt' is not a path relative to its template directoriesScoped template path is absolute, names a drive or a UNC share, or starts with / or \.Name the file relative to a template folder.
template file 'card.spider' not found in the scoped template directoriesNo template folder holds the path.Put the file in a template folder, or the host adds the folder.
a scoped template sees only args: 'secret' is not availableScoped template names anything but args and its lambda parameters, a global or ns::name included.Put the value in the map.
a scoped template calls only built-in methods and the string::, array:: and map:: functions: 'leak(...)' is not allowedScoped template calls a free or global function, or a function of a namespace other than string::, array:: and map:: (or a script's own function there).Compute the value before the render and pass it in the map.
a scoped template does not call function values: 'call(...)' is not allowedScoped template calls a function value (one in the map, a lambda, a call result).Pass the value the function would return.
raw() is not allowed in a scoped template: its output is always escapedScoped template calls raw.Render HTML the program trusts with template and pass the result.
a scoped template is one expression over args: an assignment is not allowedScoped template assigns, or uses this, new, a cast, throw, yield, include or import (a scoped template does not assign: '++' is not allowed for ++ and --).Keep the template to reads and built-in methods over args.
a scoped template's lambda takes plain parameter namesScoped template lambda has typed, reference or defaulted parameters or a capture list (a scoped template's lambda is one expression (x => expr) for a block body).Write x => expr.
a scoped template does not call a method of a class instance, a host object or a function: its code could runScoped template reaches code through a value: a method of an instance or host object (... does not apply an operator to ..., ... does not splice ..., ... does not call a built-in method over ..., ... does not test ..., ... does not index ..., ... does not key a map by ..., ... does not pass a built-in method ... for the other ways).Pass plain data: strings, numbers, arrays and maps.
a scoped template reads the plain fields of a script class instance: 'secret' is not oneScoped template reads a host property, a field with a user accessor, or a member an instance does not have.Pass the value in the map.
a scoped template indexes arrays, maps and stringsScoped template indexes another kind of value.Index an array, a map or a string.
template()'s output passed its 10485760-byte limit: the host raises it with engine::template_output_limittemplate render would pass engine::template_output_limit bytes (10 MiB by default).Render less, or the host raises the limit (0 is none).
a scoped template's output passed its 1048576-byte limit: the host raises it with engine::scoped_template_output_limitScoped render would write more than engine::scoped_template_output_limit bytes (1 MiB by default).Render less, or the host raises the limit (0 is none).
scoped_template's second argument is a mapscoped_template or scoped_template_text second argument is not a map.Pass a map.
a scoped template's lambda runs only inside its renderLambda a scoped template made is called after the render ended.Use the lambda inside the template.

Files​

TextWhenFix
Failed to open include file: helpers.jaiinclude of a file that cannot be opened.Correct the path, or add the file.
Failed to open import file: creature.jaiimport of a file that cannot be opened.Correct the path, or add the file.
parse failed: <path>:LINE:COL: error: MESSAGEA file a dynamic import(expr) reaches does not parse.Fix the parse error the message names.
Path outside the confined roots: ../secret/creds.txtinclude, import, resolve_path or file_data finds its file only outside the host's confine_paths folders.Move the file under a confined root, or the host adds its folder.
include 'part.jai' includes itself or nests too deepA literal include in a function body reaches a file it is already splicing, or splices over 32 files deep. A parse error at the include's path.Break the cycle, or import the shared file.
import(...) takes paths: strings or arrays of stringsimport(expr) gets neither a string nor an array of strings.Pass a string, or an array of them.
Insufficient privilege: filesystem.include, import, template, scoped_template or a file builtin, with the filesystem privilege disabled by the host.The host enables jai::filesystem, or the script leaves files alone.
Cannot read file 'saves/world.gqw': not foundThe runner's read_file, or crypto::sha256_file, cannot read the path (not a file, permission denied, cannot be opened, read failed alike).Correct the path; check the file exists and is readable.

Archives​

TextWhenFix
Invalid shared_ptr ID: 4from_json, from_binary or from_base64 of a handle whose object the save never wrote.Load unedited data a matching save wrote.

Exceptions​

TextWhenFix
Bare throw with no active exception thrown.throw; outside a catch block.Rethrow inside catch, or throw a value.

Coroutines​

TextWhenFix
Cannot resume a completed coroutinenext() on a finished handle, or a next(n) step past the end.Check done() before next().
Coroutine is already runningA coroutine's own body resumes it.Resume it only from outside.
next() takes 0 or 1 arguments ([count])next() with more than one argument.Pass nothing, or a step count.
next() count must be an integernext(n) with a non-int count.Pass an int.
next() count must be at least 1next(n) with a count below 1.Pass 1 or more.
advance() takes 1 argument (the variable that receives the yielded value)advance with no argument, or several.Pass the one receiving variable: while (h.advance(v)).
Coroutine has not finished: result() is available once done() is trueresult() before the body has run to its end.Drive it to the end (while (h.advance(v)), a range-for), or test done().
result() takes no argumentsresult() with arguments.Pass none.
done() takes no argumentsdone() with arguments.Pass none.
coroutine_handle has no member 'resume'A method the handle lacks, such as resume.Resume with next().

Sleep​

TextWhenFix
sleep expects a number of secondssleep gets neither an int nor a float.Pass seconds as a number.

Parallel bodies​

TextWhenFix
parallel_for: TEXT at LINE:COLA body is refused before the loop runs. parallel_transform: and parallel_reduce: lead those builtins' texts.Change the code at LINE:COL as TEXT says, or loop serially.
parallel_for: reference declaration would alias enclosing state 'g' (captured reads are read-only) at 4:12A reference bound to a variable outside the loop, or to a member of one.Bind references to the element or a local; read enclosing state by value.
parallel_for: assignment target is not allowed in a parallel body at 3:9An assignment, or a reference binding (reference declaration target alike), to storage the body cannot prove its own, such as a call's result. A conditional of lvalues names the arm it picks, each arm held to the rules. A member of a call returning a reference (pick().a = 1) raises member store must root at a local variable in a parallel body.Assign to the element, a local or out[i].
parallel_transform: first argument must be an arrayparallel_transform input is not an array (parallel_reduce: first argument must be an array alike).Pass an array.
parallel_for: can only iterate an arrayThe range is not an array.Iterate an array.
parallel_for: zipped array 2 is not an arrayA zipped value is not an array.Zip arrays.
parallel_for: zipped array 2 has 1 elements, the range has 3 (zipped arrays must have the same length)A zipped array's length differs from the range's.Zip arrays of the range's length.
parallel_for: zipped array 2 is the range itselfA zipped array is the range's own array.Zip a separate array.
parallel_transform: fn must be a script-defined functionfn is not a script function or lambda.Pass a script function or lambda.
parallel_transform: fn may not take its element by reference (elements are detached copies)fn takes its element by reference.Take it by value.
parallel_transform: expected (array, fn) or (array, fn, weight_fn)parallel_transform with another argument count (parallel_reduce: expected (array, init, step, combine) alike, under [[warn_mode]]).Pass the arguments the call takes.
parallel_transform: weight_fn must take exactly one parameter by valueweight_fn does not take one parameter by value.Declare one by-value parameter.
parallel_transform: weight_fn must return a number (element 2)The weight function returns neither an int nor a float for that element (must return a finite non-negative number for a negative, infinite or NaN weight).Return a non-negative number for every element.
parallel_transform: weight_fn must return a finite non-negative number (element 0)weight_fn returns a negative, infinite or NaN weight for that element.Return a finite, non-negative number.
parallel_transform: weight_fn failed for element 2: TEXTThe weight function raised a run-time error for that element. Its own throw arrives as thrown.Fix the weight function as TEXT says.
parallel_for: a nested parallel_for is not allowed in a parallel body (the outer loop's iterations already run in parallel: write the inner loop as for) at 4:9A parallel_for statement in the body.Write the inner loop as for.
parallel_for: nested parallel regions are not supportedA parallel loop starts while another runs, from code the statement could not see (a host callback). parallel_transform: and parallel_reduce: alike.Start the inner loop after the outer one.
parallel_for: lambdas are not allowed in a parallel bodyThe body writes a lambda.Call a named function, or a global that holds the lambda.
parallel_for: yield is not allowed in a parallel bodyThe body yields.Yield outside the loop.
parallel_for: coroutine method 'g' is not allowed in a parallel bodyThe body calls a coroutine method.Call it outside the loop.
parallel_for: function declarations are not allowed in a parallel bodyThe body declares a function (namespace and enum declarations alike).Declare it outside the loop.
parallel_for: include/import is not allowed in a parallel bodyThe body includes or imports.Include or import outside the loop.
'break' is not allowed in a parallel_for body: iterations are independent; use 'continue' for the next elementA loop-level break in the body. A parse error.Use continue or a top-level return for the next element.
parallel_for: cast<T&> is not allowed in a parallel bodycast<T&> in the body.Remove the reference cast from the body.
parallel_for: call target 'pick' is not a function known at admission timeA call through a local of the enclosing function.Call a named function, or a global that holds a function or lambda.
parallel_for: call target 'f' is not statically resolvable in a parallel bodyA call through a parameter or a local of the body.Call a named function, or a global that holds a function or lambda.
parallel_for: captured name 'twice' is a function value (only direct calls to statically-known functions are allowed in a parallel body)A function read as a value, to store it or to pass it.Call the function directly.
parallel_for: static member calls are not allowed in a parallel bodyA call to a static method of a script class.Call a free or namespace function, or call it outside the loop.
parallel_for: time:: calls are not allowed in a parallel body (engine-owned clock) at 3:41A time:: call in the body.Read the time before the loop; capture the value.
parallel_for: random::seed cannot be called on captured 'loot' in a parallel body (seed before the loop: each element draws its own stream from it) at 5:46The body, or code it reaches, reseeds a captured random.Seed before the loop. Each element's stream comes from one draw of the captured generator, the same at every worker count (In parallel loops).
parallel_for: crypto::sha256_file cannot be called in a parallel body (it reads a file) at 3:9The body, or code it reaches, hashes a file.Hash files before or after the loop. The other crypto:: functions run in a body.
parallel_for: method 'bump' on class 'Pt' is not admitted in a parallel body (only single-overload methods of the element's class or its bases) at 4:33A method call the region cannot admit.Call only single-overload methods defined on the element's own class.
parallel_for: class 'Pv' has non-public members — its methods are not admitted in a parallel bodyA method call on a class that has private members.Call methods only of classes with no private members.
parallel_for: method 'size' must be called as 'this.size()' in a parallel body (a bare call of a C++ base method)A method the body runs calls a C++ base method by its bare name.Spell it this.name().
parallel_for: body writes enclosing state 'total' at 11:31A write to a variable outside the loop.Write only the element, or total with parallel_reduce.
parallel_for: method 'push' may mutate captured state 'g'A mutating or unrecognized method called on captured state (g.push(...)), a captured object included (parallel_for: method 'push' may mutate captured state 'c').Call only the read-only builtins on it, or write a local copy or the element.
parallel_for: cannot iterate captured state 'g' by reference in a parallel body (captured reads are read-only)for (auto& v : g) over captured state.Loop with const auto&.
parallel_for: captured name 'xs' is the container being mutated (reads through it would race the element writes)A subscript read of the range's own array, or a const T& of it or of an index-written array.Read the element through the loop variable.
parallel_for: argument passes enclosing state 'grid' to reference parameter 'g' of 'peak' (captured reads are read-only; 'peak' only reads it: declare it const array<int>& g) at 6:40A variable outside the loop passed to a function's or method's non-const reference parameter that the function never writes.Declare the parameter const T&: it takes enclosing state as a captured read.
parallel_for: argument passes enclosing state 'grid' to reference parameter 'g' of 'clear', which writes it (captured reads are read-only; pass a copy, or take it as const T& where it is only read) at 6:40The same, for a parameter the function writes through.Pass a copy, or write the element (or an index write) instead.
parallel_for: reference parameter 'x' of 'bump' defaults to enclosing state 'count', which writes it (captured reads are read-only; pass a copy, or take it as const T& where it is only read) at 6:40A call to a function, method or constructor omits the argument for a non-const reference parameter whose default names a variable outside the loop.Pass a local, or declare the parameter const T& where it is only read.
parallel_for: '::K' names the program's 'K' and the body also reads a nearer 'K' (a worker holds one variable of a name: rename one)The body reads both ::K and a local K of the enclosing function.Rename the local, or read the program's variable through one spelling.
parallel_for: argument passes enclosing state 'g' by reference (captured reads are read-only) at 3:9A variable outside the loop passed to a C++ function's non-const T& parameter.Pass a copy. A C++ const T& parameter takes it as a read.
parallel_for: a counted loop must step its variable by a fixed amount toward a bound (write i++, i--, i += k or i -= k)A counted parallel_for steps another way (i *= 2, a call in the step, a step of another variable).Step by a constant or a name, or iterate an array of the indices.
parallel_for: a counted loop compares its variable with a bound (i < b, i <= b, i > b or i >= b)The condition is missing, tests another variable or uses another comparison.Compare the loop variable with its bound.
parallel_for: a counted loop declares one int variable (int i = a or auto i = a)The counted form declares a non-int, a reference, a const or several variables.Declare one int variable.
parallel_for: a counted loop must step toward its bound (i < b and i <= b count up, i > b and i >= b count down)A constant step moves away from the bound: the serial loop would not end.Flip the step or the comparison.
parallel_for: a counted loop's step must not be zeroThe step is the constant 0.Use a nonzero step.
parallel_for: a counted loop's step of -2 never reaches its bound (the serial loop would not end)A step read from a name is zero or moves away from the bound, and the loop would run at least once.Give the step the bound's direction.
parallel_for: a counted loop's bound is float, not intThe start, bound or step is not an int (a load error when its type is declared).Convert with int(...) before the loop.
parallel_for: the body writes the counted loop's variable 'i' (the loop steps it; copy it into a local to change it) at 3:40The body assigns the counted variable, or passes it to a reference parameter that writes it.Copy it into a local.
parallel_for: method 'scale' of 'Vec3' writes its object, and captured 'sun' is read-only (write a local copy, or the element) at 11:50A method that writes its object, called on a captured object or on an object a captured one holds.Copy it into a local first (Vec3 s = sun;), or keep the state in the elements.
parallel_for: member store reaches captured state 'cam' (captured reads are read-only) at 4:45A store into a field of a captured object.Write a local copy or the element.
parallel_for: captured handle 'h' is read through its members and methods only (a worker reads its own view of the object) at 3:40A captured shared_ptr used itself: compared, copied or passed.Read its members, or capture the members needed.
parallel_for: element 1 reaches the object captured as 'h' (a captured object is read-only, and an element's lane may write it)An element of the range or of a zipped array is, or holds, an object the body also reads through a captured name.Read the object through the element, or copy what the body needs before the loop.
parallel_for: captured name 'bad' is not value-semantic (an object holding a handle, a function, a var field or a C++ object)A captured object holds what no worker may copy (an object whose class runs a destructor, a script class over a C++ class, a C++ object inside a script object alike).Capture the fields the body reads.
parallel_for: captured name 'w' is not value-semantic (object/shared_ptr/weak_ptr)The body captures a weak_ptr.Capture the values the body reads.
parallel_for: member access reaches captured state 'm' (captured reads are read-only, and only a captured object has members) at 3:27A member read of a captured value that neither is nor holds an object.Subscript a container: m["k"].
parallel_for: element 0 cannot be proven exclusive (only value-semantic shapes are: primitives, strings, math vectors, value containers, flat value-class instances and distinct handles to them)Elements bound in place that the region cannot prove exclusive. Raised before the loop runs, without a position.Iterate value-semantic elements, or distinct handles to them.
parallel_for: zipped array 2 element 0 cannot be proven exclusiveThe same, for an element of a zipped array.Zip value-semantic arrays, or distinct handles.
parallel_transform: element 0: value is not value-semantic (object)An element is not a primitive, a string, a math vector, a value container, a flat value-class instance or a handle to an object no other element names.Iterate value-semantic elements.
parallel_reduce: input element 0 cannot be proven exclusiveThe same, for an element of a parallel_reduce input that holds objects.Reduce over value-semantic elements, or distinct handles.
parallel_reduce: input elements 0 and 1 hold the same object (an object the step reaches through a handle element belongs to one element)Two handle elements of the input name one object.Give each element its own object.
parallel_for: 'Tune::K' is no longer a constant (a parallel body reads only const statics of a primitive value)A class the body reads a constant of was redefined; the member is no longer a static const of a primitive value.Keep the member static const, or read it outside the loop.
parallel_reduce: step names '__jai_reduce_xs', the reduction's own inputThe step reads the name the reduction gives its input.Read the element through the step's parameter.
parallel_for: elements 0 and 3 hold the same object (an object a body reaches through a handle element belongs to one element)Two handle elements name one object.Give each element its own object.
parallel_for: elements 1 and 2 share one 'random' in field 'brain' (an element owns the C++ values it holds: give each element its own, or capture one from outside the loop)Two elements hold one bound C++ object (a random, a time::date), in the named field or, with none named, as an element of a value container. Raised before the loop runs.Give each element its own object, or draw from one random captured from outside the loop.
parallel_for: elements 2 and 5 write 'out' at the same index 4An index write out[i] = v gets one index from two elements.Give every element a distinct index.
parallel_for: body touches 'out' beyond the slot it writes, out[i] at 4:20The body writes out[i] and reads out elsewhere.Touch out only at the slot written.
parallel_for: body writes enclosing state 'out' at an index the body changes at 3:9The body writes out[i] and changes i, directly or through a T& parameter that writes it.Leave the index unchanged.
parallel_for: captured name 'out' is written at an index but is not an arrayThe body writes out[i] where out is not an array.Index-write only into an array.
parallel_reduce: step must take two parameters (acc, x)The step does not take two parameters (combine must take two parameters (a, b) alike).Declare the step as (acc, x), the combine as (a, b).
parallel_reduce: step must be a script function or lambdaThe step is not a script function or lambda.Pass a script function or lambda.
parallel_reduce: step takes its element by value (the elements are the input's, never written)The step takes its element by reference.Take it by value.
parallel_reduce: body writes enclosing state 'total' at 3:40A step the loop rules refuse raises their text under its name.Fold into the accumulator, not enclosing state.
parallel_for: body writes enclosing state 'next_id' in the constructor of 'Tick' at 2:46A construction in the body runs code that writes enclosing state (in a field initializer of 'T' and in the destructor of 'H' alike).Keep constructors, field initializers and destructors the body uses free of enclosing writes.
parallel_for: C++ class 'Sprite' is marked serial_only_constructor() and cannot be constructed in a parallel body at 3:48The body constructs a host class registered serial-only.Construct it before or after the loop.
parallel_for: class 'Glowing' has a C++ base 'Sprite' marked serial_only_constructor() and cannot be constructed in a parallel body at 4:49The body constructs a script class whose host base is registered serial-only.Construct it before or after the loop.
parallel_for: coroutine constructor of class 'Gen' is not allowed in a parallel body at 3:5The body constructs a class whose constructor is a coroutine.Construct it before or after the loop.
parallel_for: host function 'print' is marked serial_function() and cannot be called in a parallel body at 3:5A call to a host function registered serial.Call it before or after the loop.
parallel_for: C++ static method 'Sound::play' is marked serial_static_method() and cannot be called in a parallel body at 3:5A call to a host static method registered serial.Call it before or after the loop.
method 'm' was not admitted in this parallel body (admitted: single-overload public methods of the element's class or its bases touching only element, local, or captured-read state)A body refused while it runs raises the text alone; here a method call the region cannot admit.Call only the methods the text admits.
only direct field access on class instances is allowed in a parallel bodyA member read on a class instance that is not a direct field read.Read fields directly.
only direct field stores on class instances are allowed in a parallel bodyA store into a class instance that is not a direct field store.Store fields directly.
body writes enclosing state 'calls' in operator '+' of 'V' at 2:68A class operator whose body breaks the parallel body rules. The text is the rule's, as parallel_for: TEXT at LINE:COL gives it, without the prefix, naming the operator and its class.Make the operator follow the body rules, or loop serially.
converting constructor of 'T' was not admitted in this parallel body (the statement admits a conversion into a slot it can type)A conversion into a slot of class T would run its converting constructor where the statement could not type the slot, so the construction was never walked.Construct explicitly (T(x)), or convert into a slot the body declares.
A host call failed during a parallel regionA C++ function or method the body calls threw. The engine records no new text while a body runs, so the exception's text is not kept.Run the call outside the loop to read the exception's text.
custom operator dispatch on class instances is not admitted in a parallel bodyA class operator the statement never walked, such as the global [] operator.Apply it before or after the loop, or loop serially.
an assignment that changes an object's class is not admitted in a parallel bodyA subclass instance stored into a slot that holds another class.Keep each object's class unchanged in the body.
C++ method 'publish' of 'Meter' is marked serial_method() and cannot be called in a parallel bodyA call to a host method registered serial.Call it before or after the loop.
C++ method 'add' of 'Meter' changes an object this parallel body did not make (only its const methods may run on it)A non-const host method called on an object the body did not make.Call only const methods on it, or make the object in the body.
C++ property 'level' of 'Meter' is stored on an object this parallel body did not make (only an object it made takes stores)A host property stored on an object the body did not make.Store only on objects the body makes.
member 'extra' is stored on a shared object in a parallel body (a body writes its element, out[i] and the objects it made)A store into an object a host call returned that the program already holds, or into an object one of its fields holds.Change it before or after the loop, or write the element, out[i] or an object the body makes.
method 'grow' cannot run on a shared object in a parallel body (an object reached through a host call takes only its C++ class's const methods)A script method, or a method of an object with no C++ object, called on a shared object.Call it before or after the loop.
C++ call 'attach' takes a shared object that holds no C++ object in a parallel bodyA shared object with no C++ object passed to a C++ function or method.Pass it before or after the loop.
member 'on_hit' of a shared object cannot be read in a parallel body (it holds a function or a weak_ptr)A read of a shared object's field that holds a function or a weak_ptr.Read it before the loop; capture the result.
a host call in a parallel body returned an object one of its iterations owns (an element, or an object a chunk made)A host call returns an object the region gave to one iteration.Reach the element through the loop variable.
a shared object in a parallel body cannot be copied by value: its C++ object has no copy functionA by-value copy of a shared object whose C++ class registers no copy.Hold it as a shared_ptr, or copy it before the loop.
parallel_transform: type shape was not pre-warmed at the region barrier (internal) - please report this body shapeA region's thread builds a type the region did not prepare before its threads started (a library defect).Report the body; a serial loop avoids it.
parallel_transform: name 'tally' was not pre-warmed at the region barrier (internal) - please report this body shapeA region's thread needs a name the region did not prepare before its threads started (a library defect).Report the body; a serial loop avoids it.

Script layers​

TextWhenFix
Cannot copy C++ object of type 'T': the type is not copy-constructible. Hold it by reference (auto&/var&) or share it (shared_ptr<T>).A copy of a bound C++ object whose class has no copy constructor (an atomic<int>, a host type that deletes it): a by-value declaration, parameter, return, element or capture.Hold it by reference (auto&, var&, a T& parameter). A typed slot it converts into (int n = obj;) reads it without a copy.
Cannot copy an instance of nocopy class 'C': hold it by reference (auto&/var&) or share it (shared_ptr)A copy of a nocopy class instance.Hold it by reference (auto&, var&) or share it with a shared_ptr.
Script layer 'C' was detached (script_layer_detach, or a move to another engine): this handle no longer reaches its objectA handle used after its script layer was detached or moved to another engine.Stop using the handle, or take a new one.
extend: 'C' derives the C++ class 'B', which is not the object's C++ class 'O' or one of its basesextend(obj, C) names a class whose host base does not match the object.Extend with a class derived from the object's own host class or one of its bases.
extend: 'C' needs an object to extendextend(obj, C) or the host's eng->extend(obj, "C") gets null or a non-object.Pass the object to extend.

Access​

TextWhenFix
Cannot access private member 'x' of class 'C'Read or write of a private member from outside the class and its subclasses.Make it public, or use a public method.
Cannot access private constructor of class 'C'Call of a private constructor from outside the class and its subclasses.Make it public, or construct through a public static function.

Limits (catchable)​

TextWhenFix
Maximum recursion depth exceeded - possible infinite recursionActive calls reach the cap: 256 (interpreter) or 250,000 (VM) by default (engine::max_call_depth(backend, depth)).Bound the recursion, or raise the cap in the host.
Out of memoryThe platform refuses a builtin's allocation (crypto::random_bytes(n), s.repeat(n), s.pad_left(n) with n past available memory).Ask for less, or set engine::memory_cap in the host so the cap's text comes first.
Nesting too deep for the host thread's stackNesting (expressions, statements, lambdas, a long operator chain) deeper than the backend can walk on the host thread's stack. If the parser or checker gets there first, the load fails with nesting too deep for the host thread's stack in the static listing.Flatten it (name intermediate values, split a long chain), or use a thread with a larger stack.
Native stack exhausted before the call-depth cap: the host thread's stack bounds this recursionA recursion on the host thread's own stack nears its end before the call-depth cap, on either backend: interpreter calls, a top-level include reaching its own file again, script reentered from host callbacks.Bound the recursion, or use a thread with a larger stack.

The engine stays usable afterwards. On the VM a bare self tail call reuses its frame and adds no depth; the budget stops a runaway tail loop. A value nests as deep as memory allows: deep copy, ==, <=> and the orderings, to_json/from_json and to_binary/from_binary walk work lists, not the host thread's stack.

Limits (terminal: script cannot catch them)​

TextWhenFix
Script execution budget exceeded - raise engine::execution_budget or break up the workAn execute runs past its execution budget.Raise engine::execution_budget in the host, or split the work across executes.
Script execution budget exceeded - raise engine::execution_step_budget or break up the workAn execute takes more budget checks than its step budget.Raise engine::execution_step_budget in the host, or split the work across executes.
Run cancelledThe host cancels a suspended run (script_run::cancel, the run's destructor, engine teardown): the run's sleep raises it, every frame unwinds, destructors run.None in script: the host ends the run.
Script memory cap exceeded (N bytes) - raise engine::memory_cap or break up the workThe memory cap's second raise in one execute; the first is catchable.Raise engine::memory_cap in the host, or hold less at once.

Errors in script the runtime calls. Each raises its own errors: a sort comparator, a filter or remove_if predicate, the other callback helpers, a parallel_for body, a user operator, to_bool() under a condition, to_string() under string +, an accessor or post_load an archive runs.

  • The text leaves the builtin or operator unchanged and catchable; uncaught, its trace carries the callback's frames.
  • The builtin makes no further calls after the first failure; sort leaves the array as it was.
  • An archive load tolerates only a store the member itself refuses (a read-only host property, a value the field's store rejects); that member keeps its constructed value.

A caught error's e.stack and the host's format_stack_trace() list the innermost 64 frames, then one line ... N more frames. A host keeping an error result past 256 newer errors whose text embeds a value reads (the error text is no longer available) in its place.

Texts thrown to the host as jai::runtime_error, never seen by a script:

Call-depth configuration​

TextWhenFix
max_call_depth requires a built-in backend typemax_call_depth names a backend that is not built in.Pass the VM or interpreter backend.
max_call_depth must be between 1 and INT_MAXmax_call_depth gets a depth below 1 or above INT_MAX.Pass 1 to INT_MAX.
Cannot change max_call_depth during executionmax_call_depth set while a script runs.Set it before or after an execute.

Privileges​

TextWhenFix
Unknown privilege nameA named privilege no registration defines.Register it first, or correct the name.
Invalid privilege flagsFlags hold bits no privilege defines.Build flags from defined privileges.
Privilege name must not be emptyA privilege registered or named with an empty string.Name the privilege.
Cannot change privileges during a parallel regionA host function called from a parallel body enables or disables a privilege.Change privileges outside parallel regions.
reflect::is_enabled expects at least 1 argumentScript calls reflect::is_enabled with no argument.Pass the privilege to test.
reflect::is_enabled expects valid privilege flagsScript passes reflect::is_enabled flags no privilege defines.Pass a defined privilege.

Callbacks​

TextWhenFix
Cannot convert a value that is not a function to a std::function callbackconvert_script_function gets a non-function value.Pass a script function or lambda.
Cannot call a script function after its engine was destroyedThe host calls a converted callback kept past its engine.Drop the callback before the engine.

Engine entry points​

TextWhenFix
Variable 'x' not foundget_variable names a variable no script defined.Execute the defining script first, or correct the name.
Failed to open script file: <path>execute_file cannot open the path.Correct the path, or add the file.
set_backend after execute() is unsupported: defined functions and classes capture the executing backendset_backend after the engine executed code.Call set_backend before the first execute.
set_backend(interpreter) is unsupported: this build has no interpreter (link jaiscript_interpreter)set_backend(backend_type::interpreter) in a program built without the interpreter.Link jaiscript_interpreter (CMake option JAISCRIPT_INTERPRETER) in the program that compares the backends.

Suspendable runs​

TextWhenFix
A run resumes only on the thread that started itresume() or cancel() on a thread other than the run's start.Resume on the starting thread.
The run is running: it resumes only while suspendedCode the run itself is running (a host function under it) resumes or cancels it.Resume from outside the run.
The script_run holds no runresume(), cancel() or result() on a moved-from or default script_run.Use the script_run the run moved to.
Cannot start a run of a value that is not a functionstart(callable, args) gets a non-function value.Pass a function value.

Host records​

TextWhenFix
Record nesting depth exceeds the host thread's stackSave or load of host types whose serialize/save/load/load_and_construct recurse natively runs out of stack.Nest host records less deeply, or use a thread with a larger stack.
Maximum record nesting depth (1024) exceededThe same recursion passes 1024 levels where the stack cannot be asked (JAI_MAX_HOST_RECORD_DEPTH); script values nest without limit.Nest host records less deeply, or raise JAI_MAX_HOST_RECORD_DEPTH.

Conversions​

A host reads a value as a C++ type (as<T>(), as_int(), a bound function's parameter, a bound property's store) and it holds another type. The text names the held type as type_of spells it, then the type asked for. A script that caused the read catches the same text.

TextWhenFix
Cannot convert string to intA string where the host reads an int; the same text names every other pair (float, bool, char, string, array, map, object, function, weak_ptr, script class instance, a math type such as math::vec3).Pass the type the host reads, or convert in the script first.
cannot bind a non-const script reference to a C++-bound variable of a different widthA host T& parameter receives a C++-bound variable whose width or signedness differs from T.Take the parameter by value, or bind a variable of its exact type.

Values and engines​

TextWhenFix
Value outlived its engine.A held_value read after its engine was destroyed.Drop held values before their engine, or copy the data out first.
Cannot pass an object from another engine: values cross engines by copy (numbers, strings, math values and arrays and maps of them).A value handed to another engine holds something only its own engine can name (an object, a function, a pointer).Pass plain data, or rebuild the object in the receiving engine.

Archives​

Thrown as jai::serialization_error by the C++ archives (from_json, from_binary and the readers under them) when data does not match the loaded type.

TextWhenFix
Expected an object in the archive, found an integerAnother kind of value where the loaded type reads a record (an object), an array, a map or an integer. Found side: null, a bool, an integer, a float, a string, an array, an object or nothing in JSON; the end of the data or marker N in binary.Load with the type that wrote the data, or correct the data.
Archive value 300 does not fit int8An integer field's value outside its C++ type's range, or a number with a fraction (1.5, inf) read into an integer field. The field is named by width: int8 to int64, uint8 to uint64.Widen the field, or correct the data.
Property 'x' not found during deserializationA serialize/load reads a key the record lacks.Check has_property first for a key older files lack (Versions and missing fields).
Dangling shared_ptr reference: {"$id": 4} names an object this archive never defined (T)A handle refers back to an id no earlier data defined: a hand-edited or reordered file.Keep the file in the order written, or save it again.
Unknown polymorphic type: NameA $type no registrar, property_owner or binding in the archive's engine names.Register or bind the type before loading.
Polymorphic type 'Name' is not a registered subtype of requested base 'Base' (...)A $type names a registered type unrelated to the pointer's base.Declare the relation, or correct the data.
Expected '$val' for polymorphic shared_ptrA handle with a $type and no $val.Save the data again.

Saved programs​

A malformed .jaibite is refused before anything runs; every text starts jaibite: .

TextWhenFix
jaibite: truncated headerThe file ends inside its header.Save from source again.
jaibite: not a jaibite file (bad magic)The file does not start with the jaibite magic.Load a file a jaibite save wrote.
jaibite: unsupported format version M (expected N)Saved by a build of another format version (M; this build reads N).Save from source with this build.
jaibite: corrupt varintA malformed encoded number.Save from source again.
jaibite: AST nesting too deepThe saved syntax tree nests deeper than the writer or loader can walk on the thread's stack.Save or load on a thread with a larger stack, or flatten the nesting.
jaibite: type nesting too deepA saved type nests deeper than the writer or loader can walk on the thread's stack.Save or load on a thread with a larger stack, or flatten the nesting.
jaibite: missing required block statement nodeA required block is missing.Save from source again.
jaibite: expected block statement nodeA node that must be a block is something else.Save from source again.
jaibite: invalid program: local slot out of rangeA structure check fails. The other jaibite: invalid program: ... checks: a local count the file's syntax does not account for, a break outside a loop or switch (a parallel_for body is not one), a continue outside a loop, a malformed parallel_for.Save from source again.
jaibite: corrupt countEvery other load text names the damaged or foreign part: unexpected end of data, corrupt count, corrupt string index, corrupt type_info, corrupt token type, corrupt literal value, corrupt capture default, corrupt member visibility, corrupt check mode attribute, corrupt node tag N, trailing bytes after declarations, expected expression/statement/declaration node, missing required expression/statement/declaration node, destructuring name/slot count mismatch.Save from source again.
jaibite: cannot serialize unresolvable symbol idA save meets a name its engine cannot spell. jaibite: unserializable AST node type N: a node the format cannot encode.Save from source in the engine that parsed it.

Parse errors that name the JaiScript spelling. Each word is recognized only where parsing would otherwise fail, so a script using it as a name (var goto = 5;) keeps working:

WrittenText
int size() const { }JaiScript has no const methods: a method that writes no field already works on a const object
const int f() { }JaiScript has no const return types: return by value (the caller gets a copy) or by T&
array<const int>const qualifies a declaration, not a type: write const array<int> xs
shared_ptr<const T>JaiScript has no pointer to const: const shared_ptr<T> keeps the handle from rebinding, and the object stays writable
const_cast<T&>(x)JaiScript has no 'const_cast': a const stays const; copy it (auto x = c) for a writable value
constexpr int N = 4;JaiScript has no 'constexpr': a const whose initializer is a constant expression is folded at compile time: const int N = 4;
mutable int cache;JaiScript has no 'mutable' fields: every field of a const object is read-only; keep state that must change behind a shared_ptr field
[n]() mutable { ... }A lambda takes no 'mutable': its copied captures are already its own, writable and kept between calls
x = const 5'const' starts a declaration: const int x = 5;; const int x;: const 'x' needs an initializer: const int x = value;; for (const : xs): a range-for's const variable needs a name: for (const x : xs)
x instanceof int'instanceof' tests a class, and 'int' is a builtin type: compare type_of(x) == "int"; with nothing after it: expected a class name after 'instanceof'
virtual void f()JaiScript has no 'virtual': every method dispatches dynamically; mark the subclass's method 'override'
delete x;JaiScript has no 'delete': an object is freed when its last owner lets go; set the handle to null to release it
new int[5] · new T;'new' makes one shared object (new T(args)); an array is a value: array<T> a = []; · 'new T' needs its constructor's parentheses: new T() or new T(args)
goto done;JaiScript has no 'goto': use break, continue, return or a flag
super.speak()A base class method is called with super::name(args), not super.name
super(5); in a bodysuper(...) constructs the base only in a constructor's initializer list (: super(args)); call a base method with super::name(args)
&xJaiScript has no address-of '&x': bind a reference with auto& r = x, or pass x to a T& parameter
class B extends AJaiScript has no 'extends': derive with class Name : Base
a === b · a !== bJaiScript has no '===': == never converts between types, so a == b already compares without coercion ('!==' alike)
function* g()JaiScript has no 'function*': a generator is a coroutine, coroutine name(...) { yield v; }
[...a, 3], f(...args)JaiScript has no spread '...': join arrays with array::concat(a, b) (a.concat(b) appends in place), and pass arguments one by one

Other parse errors in the same voice:

  • enum value 'b' names 'c', which is not an earlier value of 'F' (an enumerator's initializer is a constant integer)
  • array<T>(...) takes a size and an optional value, not 3 arguments
  • 'uint8' is an array element type only (array<uint8>, one byte per element); a single byte is an int
  • '??=' needs a variable, a member or an element whose index runs no code; store anything else in a local first
  • A map entry binds two names, the key and the value: for (auto [k, v] : m)
  • operator! cannot be declared: !v is !to_bool(v); declare bool to_bool()
  • Nested function 'helper' cannot use enclosing local 'y': a named function captures nothing; use a lambda with a capture ([&], [=] or [y]) or function(...) / =>
  • a class cannot be declared inside a function body (a class is a program-scope type); declare it at program scope or import its file
  • 'a' names g::a by a using declaration; a variable cannot be declared with that name