Skip to content

Interrupts, effects, and handlers

AG3001 — The '!' validation syntax is not allowed on handler parameters. Validate the data inside the handler body if needed.

Default severity: error.

Handler parameters carry the payload of an interrupt, and the ! validation syntax is not allowed on them. Validation there would run at a point in the flow where a failure has nowhere safe to go.

How to fix: drop the ! from the handler parameter and validate the data inside the handler body if you need to.

AG3002 — Effect '{effect}' is declared more than once in the same file.

Default severity: error.

An effect was declared more than once in the same file. Each effect name should be introduced by a single declaration so its payload shape has one definition.

How to fix: remove the duplicate declaration.

AG3003 — Conflicting payload types for effect '{effect}'. All declarations of an effect must agree on its payload.

Default severity: error.

Two declarations of the same effect disagree about its payload type. Every declaration of an effect must agree on the data it carries.

How to fix: make the declarations match, or consolidate them into one.

AG3004 — Named arguments are not allowed on 'raise'/'interrupt'. Pass the data positionally.

Default severity: error.

raise and interrupt take their payload positionally, not as named arguments. Their data is a single positional value.

How to fix: pass the data positionally, e.g. raise MyEffect(payload).

AG3005 — Effect '{effect}' expects data {payload}, but none was supplied.

Default severity: error.

The effect declares a payload, but this raise/interrupt supplied none. A declared payload is required at the raise site.

How to fix: pass the data the effect expects.

AG3006 — Effect '{effect}' data field '{field}' is missing.

Default severity: error.

The effect's payload is a structured type, and a required field of it was not supplied at the raise site.

How to fix: add the missing field to the payload you pass.

AG3007 — Effect '{effect}' data field '{field}' has the wrong type.

Default severity: error.

A field of the effect's payload was supplied with a value whose type does not match what the effect declares for that field.

How to fix: pass a value of the declared type for that field.

AG3008 — Effect '{effect}' data does not match the declared {payload}.

Default severity: error.

The payload supplied at the raise site does not match the shape the effect declares. The whole value, not just one field, is off.

How to fix: construct the payload to match the effect's declared type.

AG3009 — Function '{fn}' may throw interrupts [{effects}] but is not inside a handler.

Default severity: warning.

This function may raise interrupts, but it is called from a place that is not inside a matching handler. An unhandled interrupt at runtime has no handle block to receive it. This is a warning because the handler may be installed dynamically at a point the checker cannot see.

How to fix: wrap the call in a handle block for the effects it may raise, or confirm a handler is installed higher up.

AG3011 — interrupt is not allowed inside a callback body (callback registered on '{hook}' may raise [{effects}]). Callbacks fire as side effects; their body cannot pause execution to ask the user a question. Move the interrupt into the calling node/function instead, or use a runtime guard if you wanted budget enforcement.

Default severity: error.

Callbacks fire as side effects at points where execution cannot pause, so their body may not interrupt — an interrupt would need to stop the run to ask the user something, which a callback has no way to do.

How to fix: move the interrupt into the calling node or function. If you only wanted a runtime budget check, use a runtime guard instead.

AG3012 — 'raises {ref}' is not an effect set. Declare '{ref}' with 'effectSet' (not 'type'), or use an inline set like '<...>'.

Default severity: error.

A raises clause must name an effect set, but the reference given is declared as a plain type, not an effectSet. The two are different: only an effect set enumerates raisable effects.

How to fix: declare the reference with effectSet instead of type, or use an inline effect set in angle brackets.

AG3013 — {kind} '{name}' raises effect '{effect}', which exceeds its declared 'raises {declared}'. Add '{effect}' to the clause.

Default severity: error.

The function or node raises an effect that its own raises clause does not list. The clause is a contract: it must cover every effect the body can raise.

How to fix: add the effect to the raises clause, or stop raising it.

AG3014 — {who} may raise any effect (its type has no 'raises' clause), which exceeds the 'raises <{allowed}>' allowed by type '{type}'. Add a 'raises' clause to the value's type.

Default severity: error.

A value is being used where the target type limits which effects may be raised, but the value's own type has no raises clause — so it could raise anything, which exceeds that limit.

How to fix: add a raises clause to the value's type so the checker can see it stays within bounds.

AG3015 — {who} raises effect '{effect}', which exceeds the 'raises <{allowed}>' allowed by type '{type}'. Add '{effect}' to the clause, or use a target type that allows it.

Default severity: error.

A value raises an effect that the target type's raises clause does not allow. The target restricts the effect set, and this value steps outside it.

How to fix: add the effect to the target type's clause, or use a target type that permits it.

AG3016 — '{callee}' can interrupt, and a finalize block cannot contain interrupts. A finalize runs while its scope shuts down, so there is nothing to resume.

Default severity: error.

An interrupt pauses the program and waits for an answer. When the answer arrives, the program resumes from the paused step. A finalize block runs while an abort shuts its scope down, so there is no step to resume from. That is why a finalize cannot interrupt, and cannot call a function that interrupts.

The check follows calls into functions defined in your own files. It cannot see into imported functions. If an imported function interrupts inside a finalize at runtime, the finalize counts as failed and the scope falls back to its saved draft.

How to fix: only compute values inside the finalize, using the variables you already have. If you need to ask the user something, ask in the normal body, before the work that can trip.

AG3017 — Cannot use {kind} at the top level of a file. Top-level code runs at initialization, which cannot branch, loop, or wait — move it inside a node or a function.

Default severity: error.

Code at the top level of a file runs when the module is initialized, not when a node executes. That phase has no way to branch, loop, or wait, so a statement that controls execution has nothing to control.

How to fix: move it inside a node or a function. Top-level code may declare things (node, def, type, imports), bind values (const x = 1), and call functions for their effect (print("ready")) — nothing else.

AG3018 — A handler cannot be registered at the top level of a file. Handlers must be inside a node or a function, where there is execution for them to guard.

Default severity: error.

A handler guards the code it wraps. At the top level of a file there is no execution to guard: the module is only being initialized, and a handler registered there would never see the interrupts it was written for.

How to fix: move the handle block inside the node or function whose work it should guard.