---
name: "Interrupts, effects, and handlers"
---

# Interrupts, effects, and handlers

<a id="ag3001"></a>

## 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.

<a id="ag3002"></a>

## AG3002 — Effect '&#123;effect&#125;' 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.

<a id="ag3003"></a>

## AG3003 — Conflicting payload types for effect '&#123;effect&#125;'. 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.

<a id="ag3004"></a>

## 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)`.

<a id="ag3005"></a>

## AG3005 — Effect '&#123;effect&#125;' expects data &#123;payload&#125;, 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.

<a id="ag3006"></a>

## AG3006 — Effect '&#123;effect&#125;' data field '&#123;field&#125;' 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.

<a id="ag3007"></a>

## AG3007 — Effect '&#123;effect&#125;' data field '&#123;field&#125;' 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.

<a id="ag3008"></a>

## AG3008 — Effect '&#123;effect&#125;' data does not match the declared &#123;payload&#125;.

*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.

<a id="ag3009"></a>

## AG3009 — Function '&#123;fn&#125;' may throw interrupts [&#123;effects&#125;] 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.

<a id="ag3011"></a>

## AG3011 — `interrupt` is not allowed inside a callback body (callback registered on '&#123;hook&#125;' may raise [&#123;effects&#125;]). 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.

<a id="ag3012"></a>

## AG3012 — 'raises &#123;ref&#125;' is not an effect set. Declare '&#123;ref&#125;' with 'effectSet' (not 'type'), or use an inline set like '&lt;...&gt;'.

*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.

<a id="ag3013"></a>

## AG3013 — &#123;kind&#125; '&#123;name&#125;' raises effect '&#123;effect&#125;', which exceeds its declared 'raises &#123;declared&#125;'. Add '&#123;effect&#125;' 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.

<a id="ag3014"></a>

## AG3014 — &#123;who&#125; may raise any effect (its type has no 'raises' clause), which exceeds the 'raises &lt;&#123;allowed&#125;&gt;' allowed by type '&#123;type&#125;'. 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.

<a id="ag3015"></a>

## AG3015 — &#123;who&#125; raises effect '&#123;effect&#125;', which exceeds the 'raises &lt;&#123;allowed&#125;&gt;' allowed by type '&#123;type&#125;'. Add '&#123;effect&#125;' 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.

<a id="ag3016"></a>

## AG3016 — '&#123;callee&#125;' 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.

<a id="ag3017"></a>

## AG3017 — Cannot use &#123;kind&#125; 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.

<a id="ag3018"></a>

## 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.

<a id="ag3019"></a>

## AG3019 — @&#123;tag&#125; names '&#123;field&#125;', which effect '&#123;effect&#125;' does not carry.

*Default severity: error.*

An `@always` or `@alwaysUnder` tag names a field that the effect's payload does not declare. The tag can only pin fields the interrupt actually carries.

```
@always(nam)
effect app::env { name: string }
```

**How to fix:** name a field from the payload type, or add the field to the payload.

<a id="ag3020"></a>

## AG3020 — @&#123;tag&#125; arguments must be bare field names, each named once (effect '&#123;effect&#125;').

*Default severity: error.*

Each argument to `@always` or `@alwaysUnder` must be a bare field name, and no field may be named twice across the two tags. Strings, calls, and other expressions are not field names.

```
@always("name")
effect app::env { name: string }
```

**How to fix:** write `@always(name)`, and name each field in only one of the two tags.

<a id="ag3021"></a>

## AG3021 — @&#123;tag&#125; appears more than once on effect '&#123;effect&#125;'.

*Default severity: error.*

The same tag appears more than once on one effect declaration. Each of `@always` and `@alwaysUnder` may appear at most once; list every field in that one tag.

```
@always(a)
@always(b)
effect app::x { a: string, b: string }
```

**How to fix:** merge them into one tag, e.g. `@always(a, b)`.

<a id="ag3022"></a>

## AG3022 — Conflicting @always scopes for effect '&#123;effect&#125;'. All tagged declarations of an effect must agree.

*Default severity: error.*

Two tagged declarations of the same effect disagree about which fields an "approve always here" rule pins. Every tagged declaration must name the same fields with the same tag; an untagged declaration inherits the tagged scope and is fine.

**How to fix:** make the tags match, or drop the tag from one declaration so it inherits the other.

<a id="ag3023"></a>

## AG3023 — @&#123;tag&#125; is only valid on an effect declaration.

*Default severity: error.*

An `@always` or `@alwaysUnder` tag ended up on something other than an effect declaration, such as a function, a type, or an import. These tags only describe an effect's approval scope.

**How to fix:** move the tag so it sits directly above the `effect` line it describes.

<a id="ag3024"></a>

## AG3024 — Unknown capability '&#123;name&#125;' on '&#123;callable&#125;'. Did you mean '&#123;suggestion&#125;'? The capabilities are &#123;known&#125;.

*Default severity: error.*

A `@capabilities` tag names something that is not a capability. The names are fixed: `fileRead`, `fileWrite`, `network`, `subprocess`, `env`, `terminal`, and `llm`. Each one is a part of the host that a platform may lack, so a program cannot add to the list.

```
@capabilities(flies)
def load(path: string): string { ... }
```

**How to fix:** write the name the message suggests, `@capabilities(fileRead)` here.

<a id="ag3025"></a>

## AG3025 — @capabilities arguments must be bare capability names (on '&#123;callable&#125;').

*Default severity: error.*

Each argument to `@capabilities` must be a bare capability name. Strings, calls, and other expressions are not names.

```
@capabilities("fileRead")
def load(path: string): string { ... }
```

**How to fix:** write `@capabilities(fileRead)`.

<a id="ag3026"></a>

## AG3026 — @capabilities appears more than once on '&#123;callable&#125;'.

*Default severity: error.*

`@capabilities` appears more than once on one function or node. It may appear once; list every capability in that one tag.

```
@capabilities(fileRead)
@capabilities(network)
def sync(path: string): string { ... }
```

**How to fix:** merge them: `@capabilities(fileRead, network)`.

<a id="ag3028"></a>

## AG3028 — @capabilities goes on a def or a node.&#123;hint&#125;

*Default severity: error.*

A `@capabilities` tag ended up on something other than a function or a node: an effect declaration, a type, a constant, a bare call, or nothing at all. The tag says what a function needs from the host, and only a `def` or a `node` carries it. A wrapper that calls a tagged function needs no tag of its own; it inherits the need through the call.

```
@capabilities(subprocess)
effect app::shell { command: string }
```

**How to fix:** move the tag so it sits directly above the `def` or `node` that asks the host for the capability. For an effect, that is the function that raises it.

<a id="ag3029"></a>

## AG3029 — &#123;kind&#125; '&#123;name&#125;' needs the &#123;capability&#125; capability, which the &#123;platform&#125; platform does not have.
&#123;path&#125;

*Default severity: error.*

The program is being compiled for a platform (`--platform`, or `platform` in agency.json) that lacks a capability one of its functions needs. A function needs what its own `@capabilities` tag names and what the functions it calls need. The lines after the message show the calls from the node or exported function to the function whose tag carries the capability. The browser platform, for example, has no `fileRead`, so a node that calls `read` cannot run there. A handler does not help: approving the read would not make the browser able to do it.

**How to fix:** take the call out of the program for that platform, or compile for a platform that has the capability.

<a id="ag3030"></a>

## AG3030 — &#123;kind&#125; '&#123;name&#125;' raises effect '&#123;effect&#125;', which exceeds its declared 'raises &#123;declared&#125;'. It is raised by decorator '&#123;decorator&#125;'. Add '&#123;effect&#125;' to the clause.

*Default severity: error.*

A decorator raises an effect that the decorated function's `raises` clause does not list. This is the decorator form of AG3013.

A decorated function's effects are its decorators' effects plus its body's, because the decorator's code runs every time the function is called. A `@budgeted` decorator written over `guard` raises `std::guard`, so a function it decorates raises `std::guard` too.

**How to fix:** add the effect to the clause.
