Skip to main content

When Expressions Fail

This page explains what happens when an expression cannot produce an answer — and why the run stops rather than guessing.

The failure contract

  • Undefined arithmetic fails the run with a structured diagnostic naming the failing character span: division by zero, arithmetic on null or on an absent value, and any other operation with no defined result. Nothing silently absorbs to zero — an author who wants a default writes COALESCE or IF, which is visible in the ruleset text and type-checked, rather than relying on a missing invoice amount quietly becoming a legitimate-looking zero-amount booking.
  • Everything statically decidable is caught at save time: an unknown function, the wrong arity, malformed syntax, an invalid date pattern, an unrepresentable path, a provably-mismatched type, and a regex outside the permitted subset are all diagnostics attached to the ruleset before it ever runs. Saving itself is never blocked — a draft mid-edit must stay savable — but a ruleset carries a blocking flag while unresolved static errors remain, and that flag (not the diagnostic itself) is what gates review, publish and run submission.
  • A step's optional onError fallback is checked against that step's declared output type at save time, and firing it is recorded in the trace alongside the diagnostic it suppressed — a silently swallowed error would defeat the whole audit requirement.
  • A failing run still writes the full partial trace, and the node that failed carries the diagnostic's code, its dot-path location, and its character span. A failed run is exactly when someone — most often a consultant debugging a customer's ruleset — needs the trace the most.