Table of Contents

Error Model

Expr reports errors when script text cannot be parsed, when evaluation cannot continue, or when a script intentionally raises an error.

Errors stop the current evaluation unless the host object or host integration explicitly documents different behavior.


Error Categories

Expr errors commonly fall into these categories:

Category When it happens Example
Parse error Script text is syntactically invalid. Missing `;`, `)`, `}`, or invalid placement of `include`.
Runtime error Script syntax is valid, but evaluation fails. Division by zero, invalid operands, undefined function.
Built-in function error A built-in function receives invalid arguments or an invalid domain value. `sqrt(-1)`, wrong argument count.
Object method error An object method is missing or receives invalid arguments. `array().unknown_method()`.
User error The script calls `error(…)`. `error('Invalid feed rate')`.
Host error A host-provided object or function cannot complete its operation. File, Python, serial, dialog, or settings operation fails.

Parse Errors

Parse errors happen before the script starts running.

Common parse errors include:

Example:

a = 10
b = 20;     // parse error near this line because previous semicolon is missing

Example:

if (ready)
{
    include 'Library.expr'     // parse error: include is top-level only
}

When an error appears near a line that looks correct, also check the previous statement.


Runtime Errors

Runtime errors happen while the script is being evaluated.

Common runtime errors include:

Examples:

unknownFunc();       // undefined function
10 / 0;              // division by zero
none() + 1;          // invalid arithmetic operand
items.unknown();     // object method does not exist

User Errors

Use `error(…)` when a script detects a condition that should stop evaluation.

`error(…)` builds a message from all arguments and raises an error.

function RequirePositive(name, value)
{
    if (!value.is_num_notnan())
    {
        error(name, ' must be a valid number');
    }
 
    if (value <= 0)
    {
        error(name, ' must be positive');
    }
 
    return value;
}
 
feed = RequirePositive('Feed rate', feed);

Use specific messages. They make script failures easier to diagnose from host logs or UI output.


none(), nan(), and Errors

`none()` is a value, not an error.

Use `none()` when a result is intentionally missing and the caller can continue.

function FindTool(number)
{
    if (number <= 0)
    {
        return none();
    }
 
    return 'T' + number;
}

`nan()` is also a value. It represents an invalid numeric result, but it is still a number value.

Use `error(…)` when continuing would be unsafe or misleading.

if (toolDiameter.is_none())
{
    error('Tool diameter is required');
}

See none(), nan(), and errors and Type system.


Argument Errors

Functions, constructors, and methods check their argument count.

function Add(a, b)
{
    return a + b;
}
 
Add(1);          // error
Add(1, 2, 3);    // error

Built-in objects do the same:

array(1, 2);
serial(1);       // error: serial expects no constructor arguments

When an error mentions expected argument count, check both missing arguments and extra trailing arguments.


Type and Domain Errors

Many operators and functions require specific value types.

'10' * 2;        // error: numeric operator needs numbers
'5' > 3;         // error: numeric comparison needs numbers

Some numeric functions have domain rules:

sqrt(-1);        // error
atan2(0, 0);     // error

Check values before calling strict numeric operations:

if (!value.is_num_notnan())
{
    error('Expected a usable number');
}

Include Errors

Include errors happen during parsing.

Common include errors include:

Example:

include 'missing.expr'       // file does not exist

For namespaced includes, remember that imported functions and classes must be called with the alias:

include 'Math.expr' as MathLib
 
MathLib::Add(1, 2);          // OK
Add(1, 2);                   // error unless another Add exists

See Include system.


Object and Host Errors

Object APIs can report failure in different ways. Check the object reference page for the exact behavior.

Common patterns:

Examples:

img = image_data().load('missing.png');
if (!img.valid)
{
    print(img.error);
}
port = serial();
if (!port.open('COM1'))
{
    print(port.last_error());
}

A host object that uses callbacks may report callback errors to the output stream and stop the operation. For example, `timer` stops if its callback raises an error.


Protected Names

Some host/system object names are protected and cannot be overwritten by assignment.

settings = 1;    // error
session = 1;     // error
python = 1;      // error

Protected global objects should be used through their methods and properties.


Error Messages

Error messages are intended to be short and direct.

They usually identify:

Typical examples:

Expected ';' after expression
Call to undefined function 'Foo'
Recursive include detected: MyFile.expr

Exact text can vary by host version and by the object that reports the error.


Debugging Checklist

When a script fails:

  1. Reduce the script to the smallest version that still fails.
  2. Check syntax first: semicolons, parentheses, braces, commas, and conditional `:`.
  3. Check whether the error is parse-time or runtime.
  4. Validate include paths and namespace aliases.
  5. Check function, constructor, and method argument counts.
  6. Check operand types before numeric and bitwise operators.
  7. Guard unsafe values with methods such as `is_none()`, `is_num()`, and `is_num_notnan()`.
  8. Replace silent fallback behavior with explicit `error(…)` when bad input should stop the script.

Previous: Include system

Next: Execution model and sessions