Skip to main content

The hierarchy

Every failure Sense can raise is a SenseError subclass, each carrying a source line number when one is known:
A Sense program should never surface a raw Python traceback for a user-level mistake. Every error path in the interpreter is designed to raise one of these, with a message that says what went wrong and, where useful, what to do about it.

How the CLI presents them

exit code 1. A RecursionError (Python’s own stack-overflow signal, for deeply recursive Sense programs) is caught separately and presented as SenseError: maximum recursion depth exceeded rather than a raw traceback.

Errors with a distinct “did you mean” message

A handful of lexer errors are deliberately more specific than “unexpected character,” aimed at people (and LLMs) whose habits default to another language’s syntax:

Common runtime errors, by cause

x: Int = "nope", or calling f(a: Int) with a String, or a function declared returns Int that returns a String. See Values & Types.
Reading a name nothing in the enclosing scope chain ever bound. See Variables & Scope.
1 / 0 and 1 % 0 both raise — Sense never returns inf/nan silently.
Every declared function/action parameter must be supplied exactly once per call — no defaults, no variadic user-defined functions yet.
.commit() before .verify(), verifying or committing twice, calling start() on an already-started agent, resume() on a non-paused agent — see Actions and Pause & Resume.
SensePolicyError specifically — an action’s requires capability was denied by the nearest applicable policy rule. See Policy.
SenseApprovalError specifically — an action declared requires approval was .commit()-ted before <action>.approve() was ever called. See Actions.
SenseImportError, naming the cycle or the resolved path that wasn’t found. See Modules.

Continue

Builtins reference

What each builtin raises and when.

CLI reference

How sense run/sense repl behave around errors.