Skip to main content
Lion uses Effect to model computation, which means errors are values tracked in the type system rather than exceptions thrown at runtime. When something goes wrong during evaluation — a bad argument, an unresolvable function call, or a malformed expression — Lion fails the Effect with a typed error that you can match, recover from, or propagate without a try/catch anywhere in sight.

The EvaluateResult type

The return type of run and the internal evaluate function is EvaluateResult:
EvaluateResult is Effect<unknown, ParseError | ArgumentMismatchError | InvalidFunctionCallError, LionEnvironmentService>. The three type parameters are the success value, the union of possible errors, and the required service. run provides LionEnvironmentService automatically from the environment you pass, so by the time you reach Effect.runPromise the requirement is fully satisfied.

Error types

ParseError

Produced by Effect Schema when the input to run does not match LionExpressionSchema. This happens before any evaluation occurs — the input is not a valid Lion expression at all. A ParseError carries a structured description of what was expected versus what was received.

ArgumentMismatchError

Raised when a stdlib function receives arguments of the wrong type. For example, passing a string where a number is required in number/add. The _tag field is "ArgumentMismatchError".

InvalidFunctionCallError

Raised when an array expression’s first element does not resolve to a callable value. If Lion evaluates ["notAFunction", 1, 2] and notAFunction is not a function in the environment, evaluation fails with this error. The expression field contains the original Lion expression for debugging. The _tag field is "InvalidFunctionCallError".

Handling all errors with Effect.catchAll

Effect.catchAll intercepts any failure in the Effect and lets you return a fallback value or a new Effect:
The error parameter is typed as ParseError | ArgumentMismatchError | InvalidFunctionCallError, so your editor will offer completions for all available fields.

Handling specific error types with Effect.catchTag

When you only want to recover from one kind of error, use Effect.catchTag. Tags correspond to the class names: "ArgumentMismatchError", "InvalidFunctionCallError", and "ParseError".
Errors not matched by a catchTag remain in the failure channel and propagate to the next handler or to runPromise, which will reject the returned Promise.

Surfacing parse errors separately

ParseError arrives from Effect Schema’s Schema.decodeUnknown call inside run. You can intercept it before the other errors to give users a distinct message when the input is structurally invalid:
ParseError from Effect Schema does not have a _tag property matching "ParseError" in the same way as the Lion-specific errors. Catch it with Effect.catchTag("ParseError", ...) or use Effect.catchAll to handle all errors uniformly.

Letting errors propagate as rejected Promises

If you prefer to handle errors in a traditional try/catch, do not add any catchAll or catchTagEffect.runPromise will reject the Promise when the Effect fails:
This works but loses the compile-time exhaustiveness guarantee that Effect provides. Prefer the typed Effect combinators when possible.