---
title: "Protocol expression reference"
description: "Every function, operator and name protocol expressions may use, where each name is in scope, the limits, and every check rejection with its fix."
editUrl: true
head: []
template: "doc"
sidebar: {"hidden":false,"attrs":{}}
pagefind: true
draft: false
---

> For the complete documentation index optimized for AI agents, see [llms.txt](https://docs.arete.run/llms.txt) or [llms-full.txt](https://docs.arete.run/llms-full.txt). A markdown version of this page is available at [/reference/protocol-expressions.md](https://docs.arete.run/reference/protocol-expressions.md) or by sending `Accept: text/markdown`.
{/* Generated by docs/scripts/protocol-expressions.mjs from src/data/protocol-expressions.json. Do not edit by hand. */}

Guards, derived states, reaction triggers, binds, glue, fees and instruction
templates are written as expressions. This page is generated from the
reference that Arete's protocol checker exports, so it lists exactly what an
upload accepts. `npx arete-protocol check` runs a local check of syntax and
names. With a secret key, `npx arete-protocol check`,
`a4 protocol deploy --dry-run` and the MCP tool `protocol_check` also run
the server's checks, without uploading anything.

## Values

- **Integers** are written as numbers: `1000`, `-3`. Protocol integer
  math is exact and fails on overflow or division by zero; there are no
  floats. A float literal such as `1.5` parses but fails when evaluated.
- **u64 and larger values** arrive in JSON as decimal strings (an arg with
  `format: "u64"` is `"1500"`). They are typed as integers, so
  `args.amount >= 1000` works, and comparisons are by value.
- **Strings** are JSON strings: `"vault-"`, with JSON escapes.
- **Public keys** are base58 strings. A string literal is accepted wherever a
  public key is expected: `wallet == "So11111111111111111111111111111111111111112"`.
- **Booleans and null**: `true`, `false`, `null` (also `none`).
- **Byte arrays** are written `[1, 2, 3]`: integers from 0 to 255, for
  seeds and byte arguments. After a value, brackets index it instead:
  `resources.venues[1].reserve` (see [Operators](#operators)). After
  `in`, they hold a list of values: `args.side in ["bid", "ask"]`.

## Operators

All binary operators are left-associative; a higher precedence binds
tighter. Use parentheses to group. Comparisons other than `==` and `!=`
compare integers.

| Operator                                 | Precedence | Returns                   | Meaning                                                                                                                                                                                                                                                                                        |
| ---------------------------------------- | ---------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `x[<integer literal>]` (postfix)         | 13         | the array's item type     | One item of an array. The index must be an integer literal (an index computed from args fails the check: use a literal index, or `in` for membership), and an index at or past the array's maxItems fails as index-out-of-range. Missing items are null. Example: `resources.allowedMints[0]`. |
| `x[<integer literal>].<field>` (postfix) | 13         | the field's schema type   | A field of an indexed item, typed from the array's item schema (items.properties). Example: `resources.venues[1].reserve`.                                                                                                                                                                     |
| `!` (prefix)                             | 12         | bool                      | Logical not; binds tighter than every binary operator.                                                                                                                                                                                                                                         |
| `*`                                      | 11         | the type of the left side | Multiply.                                                                                                                                                                                                                                                                                      |
| `/`                                      | 11         | the type of the left side | Divide. In protocols, integer division truncates and fails on division by zero.                                                                                                                                                                                                                |
| `%`                                      | 11         | the type of the left side | Remainder.                                                                                                                                                                                                                                                                                     |
| `+`                                      | 10         | the type of the left side | Add. In protocols, integer math is exact and fails on overflow.                                                                                                                                                                                                                                |
| `-`                                      | 10         | the type of the left side | Subtract.                                                                                                                                                                                                                                                                                      |
| `<<`                                     | 9          | the type of the left side | Shift left.                                                                                                                                                                                                                                                                                    |
| `>>`                                     | 9          | the type of the left side | Shift right.                                                                                                                                                                                                                                                                                   |
| `<`                                      | 8          | bool                      | Less than (integers).                                                                                                                                                                                                                                                                          |
| `<=`                                     | 8          | bool                      | Less than or equal (integers).                                                                                                                                                                                                                                                                 |
| `>`                                      | 8          | bool                      | Greater than (integers).                                                                                                                                                                                                                                                                       |
| `>=`                                     | 8          | bool                      | Greater than or equal (integers).                                                                                                                                                                                                                                                              |
| `==`                                     | 7          | bool                      | Equal. Integers compare by value, whether written as numbers or decimal strings.                                                                                                                                                                                                               |
| `!=`                                     | 7          | bool                      | Not equal.                                                                                                                                                                                                                                                                                     |
| `in`                                     | 7          | bool                      | Membership: `x in [a, b]` is `x == a \|\| x == b`; `x in resources.allowed` checks every element of an array value. Element types must match (a string literal can stand for a public key). Protocols only.                                                                                    |
| `&`                                      | 6          | the type of the left side | Bitwise and.                                                                                                                                                                                                                                                                                   |
| `^`                                      | 5          | the type of the left side | Bitwise exclusive or.                                                                                                                                                                                                                                                                          |
| `\|`                                     | 4          | the type of the left side | Bitwise or.                                                                                                                                                                                                                                                                                    |
| `&&`                                     | 3          | bool                      | Logical and; the right side is evaluated only when the left is true.                                                                                                                                                                                                                           |
| `\|\|`                                   | 2          | bool                      | Logical or; the right side is evaluated only when the left is false.                                                                                                                                                                                                                           |
| `??`                                     | 1          | the type of the left side | The left side, or the right side when it is null. The right side must be a literal.                                                                                                                                                                                                            |

## Functions

40 functions are available in protocols. Arguments
marked `integer literal` or `string literal` must be written as literals.

| Function                                | Returns                       | What it does                                                                                                                                                              | Example                                       |
| --------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- |
| `if(condition, then, else)`             | the type of `then`            | `then` when the condition is true, otherwise `else`. Both branches must have compatible types.                                                                            | `if(args.amount > 1000, args.amount, 1000)`   |
| `some(value)`                           | the type of `value`, nullable | Marks a value as optional (`Option::Some`).                                                                                                                               | `some(args.amount)`                           |
| `exists(value)`                         | bool                          | True when the value is not null.                                                                                                                                          | `exists(reads.vault.amount)`                  |
| `is_some(value)`                        | bool                          | True when the value is not null (the same as `exists`).                                                                                                                   | `is_some(reads.vault.amount)`                 |
| `is_none(value)`                        | bool                          | True when the value is null.                                                                                                                                              | `is_none(reads.vault.amount)`                 |
| `is_null(value)`                        | bool                          | True when the value is null (the same as `is_none`).                                                                                                                      | `is_null(reads.vault.amount)`                 |
| `abs(n)`                                | the type of `n`, nullable     | Absolute value; null when `n` is null.                                                                                                                                    | `abs(params.rate)`                            |
| `min(a, b)`                             | the type of `a`, nullable     | The smaller of two numbers; null when either is null.                                                                                                                     | `min(args.amount, reads.vault.amount)`        |
| `max(a, b)`                             | the type of `a`, nullable     | The larger of two numbers; null when either is null.                                                                                                                      | `max(args.amount, 1000)`                      |
| `ui_amount(amount, decimals)`           | f64                           | A raw token amount scaled down by its decimals. **Checks, but protocol evaluation rejects it**: avoid it in protocols.                                                    | `ui_amount(args.amount, params.decimals)`     |
| `raw_amount(amount, decimals)`          | u64                           | A UI token amount scaled up by its decimals. **Checks, but protocol evaluation rejects it**: avoid it in protocols.                                                       | `raw_amount(args.amount, params.decimals)`    |
| `concat(a, b, ...)`                     | string                        | Joins two or more scalars into a string; null when any part is null.                                                                                                      | `concat(args.label, "-", args.amount)`        |
| `starts_with(text, prefix)`             | bool?                         | Whether `text` begins with `prefix`; null when either is null.                                                                                                            | `starts_with(args.label, "vault-")`           |
| `split_part(text, separator, position)` | string?                       | The `position`-th field (1-based) of `text` split on `separator`; null when out of range.                                                                                 | `split_part(args.label, ":", 2)`              |
| `utf8(bytes)`                           | string?                       | Bytes as UTF-8 text; null when they are not valid UTF-8.                                                                                                                  | `utf8(args.seed)`                             |
| `len(value)`                            | u64                           | The number of items in an array, or of bytes in a string.                                                                                                                 | `len(args.seed)`                              |
| `sum(array)`                            | u64                           | The sum of an array of integers.                                                                                                                                          | `sum(args.seed)`                              |
| `index(array, i)`                       | any                           | The item at a literal, 0-based position; null when out of range. The result is untyped.                                                                                   | `index(args.seed, 0)`                         |
| `slice(array, start, end)`              | the type of `array`           | The items from `start` up to (not including) `end`, both literal and clamped to the array.                                                                                | `slice(args.seed, 0, 8)`                      |
| `u64_from_le_bytes(bytes)`              | u64                           | Reads 8 little-endian bytes as a u64. **Checks, but protocol evaluation rejects it**: avoid it in protocols.                                                              | `u64_from_le_bytes(reads.vault.data)`         |
| `u64_from_be_bytes(bytes)`              | u64                           | Reads 8 big-endian bytes as a u64. **Checks, but protocol evaluation rejects it**: avoid it in protocols.                                                                 | `u64_from_be_bytes(reads.vault.data)`         |
| `keccak256(bytes)`                      | bytes                         | The Keccak-256 hash of the bytes. **Checks, but protocol evaluation rejects it**: avoid it in protocols.                                                                  | `keccak256(args.seed)`                        |
| `slot()`                                | u64                           | The slot of the update being processed. **Checks, but protocol evaluation rejects it**: avoid it in protocols.                                                            | `slot()`                                      |
| `timestamp()`                           | i64                           | The current Unix time in seconds (in protocols, the same as `now`).                                                                                                       | `timestamp()`                                 |
| `pda(program, name, [seed, ...])`       | pubkey                        | Derives a PDA the program's IDL names: the program alias, the PDA's name, then its non-constant seeds in order. A PDA with no non-constant seeds takes none.              | `pda("vault", "escrow", wallet, args.amount)` |
| `ata(owner, mint)`                      | pubkey                        | The classic SPL associated token account of `owner` for `mint`.                                                                                                           | `ata(wallet, resources.mint)`                 |
| `u8(value)`                             | u8                            | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `u8(params.decimals)`                         |
| `u16(value)`                            | u16                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `u16(params.decimals)`                        |
| `u32(value)`                            | u32                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `u32(args.amount)`                            |
| `u64(value)`                            | u64                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `u64(params.rate)`                            |
| `u128(value)`                           | u128                          | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `u128(args.amount)`                           |
| `i8(value)`                             | i8                            | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `i8(params.decimals)`                         |
| `i16(value)`                            | i16                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `i16(params.decimals)`                        |
| `i32(value)`                            | i32                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `i32(params.rate)`                            |
| `i64(value)`                            | i64                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `i64(args.amount)`                            |
| `i128(value)`                           | i128                          | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `i128(args.amount)`                           |
| `f32(value)`                            | f32                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range. **Checks, but protocol evaluation rejects it**: avoid it in protocols. | `f32(args.amount)`                            |
| `f64(value)`                            | f64                           | Converts a value to this type; null stays null. Integer casts fail when the value is out of range. **Checks, but protocol evaluation rejects it**: avoid it in protocols. | `f64(args.amount)`                            |
| `string(value)`                         | string                        | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `string(args.amount)`                         |
| `bool(value)`                           | bool                          | Converts a value to this type; null stays null. Integer casts fail when the value is out of range.                                                                        | `bool(exists(reads.vault.amount))`            |

`exp`, `ln`, `pow` are float math, available in stack
sources but not in protocols.

### Argument types

| Function            | Argument    | Type            |
| ------------------- | ----------- | --------------- |
| `if`                | `condition` | bool            |
| `if`                | `then`      | any             |
| `if`                | `else`      | any             |
| `some`              | `value`     | any             |
| `exists`            | `value`     | any             |
| `is_some`           | `value`     | any             |
| `is_none`           | `value`     | any             |
| `is_null`           | `value`     | any             |
| `abs`               | `n`         | integer         |
| `min`               | `a`         | integer         |
| `min`               | `b`         | integer         |
| `max`               | `a`         | integer         |
| `max`               | `b`         | integer         |
| `ui_amount`         | `amount`    | number          |
| `ui_amount`         | `decimals`  | integer         |
| `raw_amount`        | `amount`    | number          |
| `raw_amount`        | `decimals`  | integer         |
| `concat`            | `a`         | scalar          |
| `concat`            | `b`         | scalar          |
| `starts_with`       | `text`      | string          |
| `starts_with`       | `prefix`    | string          |
| `split_part`        | `text`      | string          |
| `split_part`        | `separator` | string          |
| `split_part`        | `position`  | integer literal |
| `utf8`              | `bytes`     | bytes           |
| `len`               | `value`     | any             |
| `sum`               | `array`     | array           |
| `index`             | `array`     | array           |
| `index`             | `i`         | integer literal |
| `slice`             | `array`     | array           |
| `slice`             | `start`     | integer literal |
| `slice`             | `end`       | integer literal |
| `u64_from_le_bytes` | `bytes`     | bytes           |
| `u64_from_be_bytes` | `bytes`     | bytes           |
| `keccak256`         | `bytes`     | bytes           |
| `pda`               | `program`   | string literal  |
| `pda`               | `name`      | string literal  |
| `pda`               | `seed`      | any             |
| `ata`               | `owner`     | pubkey          |
| `ata`               | `mint`      | pubkey          |
| `u8`                | `value`     | any             |
| `u16`               | `value`     | any             |
| `u32`               | `value`     | any             |
| `u64`               | `value`     | any             |
| `u128`              | `value`     | any             |
| `i8`                | `value`     | any             |
| `i16`               | `value`     | any             |
| `i32`               | `value`     | any             |
| `i64`               | `value`     | any             |
| `i128`              | `value`     | any             |
| `f32`               | `value`     | any             |
| `f64`               | `value`     | any             |
| `string`            | `value`     | any             |
| `bool`              | `value`     | any             |

## Names

| Name                        | Type                       | What it is                                                                                                 |
| --------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `now`                       | i64                        | The current Unix time in seconds.                                                                          |
| `deployment.id`             | string                     | The deployment's id.                                                                                       |
| `deployment.attestation`    | pubkey                     | The deployment's attestation public key.                                                                   |
| `deployment.squadsProposer` | pubkey?                    | The calling account's Squads proposer; null when no step uses squadsProposer.                              |
| `params.<name>`             | the param's schema type    | An instance param, fixed when the instance is created (nested object fields as params.\<name\>.\<field\>). |
| `resources.<name>`          | the resource's schema type | A deployment resource, published before activation (nested fields as resources.\<name\>.\<field\>).        |
| `wallet`                    | pubkey                     | The wallet calling the step (in a participant machine, the participant's wallet).                          |
| `args.<name>`               | the arg's schema type      | An argument of the step being called.                                                                      |
| `ephemeral.<name>`          | pubkey                     | A fresh keypair the step allocates (step.ephemeral).                                                       |
| `reads.<read>.exists`       | bool                       | Whether the read account exists.                                                                           |
| `reads.<read>.address`      | pubkey                     | The read account's address.                                                                                |
| `reads.<read>.lamports`     | u64                        | The read account's lamports.                                                                               |
| `reads.<read>.amount`       | u64                        | A token account read's balance (tokenAccount reads).                                                       |
| `reads.<read>.mint`         | pubkey                     | A token account read's mint (tokenAccount reads).                                                          |
| `reads.<read>.owner`        | pubkey                     | A token account read's owner (tokenAccount reads).                                                         |
| `reads.<read>.<field>`      | any                        | A decoded field of a program account read (account reads), typed by the program's IDL at run time.         |
| `instance.id`               | string                     | The instance's id.                                                                                         |
| `instance.state`            | string                     | The instance machine's current state.                                                                      |
| `instance.accounts.<name>`  | pubkey                     | An account the create step bound (create step bind.accounts).                                              |
| `instance.roles.<role>`     | pubkey                     | The wallet holding a role.                                                                                 |
| `participant.id`            | string                     | The participant's id.                                                                                      |
| `participant.state`         | string                     | The participant machine's current state.                                                                   |
| `participant.wallet`        | pubkey                     | The participant's wallet.                                                                                  |

## Where each name is in scope

The checker gives each expression the names of the place it sits in. A name
outside its place is an `unknown-reference`. "When declared" roots exist only
if the spec declares them: `args.*` when the step has args, `reads.*` for the
reads the step or machine lists, and so on.

| Site                  | Where                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | Always in scope                                          | When declared                                                                   | Notes                                                                                                                                                                                       |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `create-step`         | `/steps/<step>/guards/<i>/expr`<br />`/steps/<step>/bind/accounts/<name>`<br />`/steps/<step>/bind/roles/<role>`<br />`/steps/<step>/fee/asset/mint`<br />`/steps/<step>/glue/atas/<i>/owner`<br />`/steps/<step>/glue/atas/<i>/mint`<br />`/steps/<step>/glue/wrapSol/amount`<br />`/steps/<step>/build/instructions/<i>/args/<name>`<br />`/steps/<step>/build/instructions/<i>/accounts/<name>`<br />`/steps/<step>/build/instructions/<i>/remainingAccounts/<k>/pubkey` | `now`, `deployment`, `wallet`                            | `params`, `resources`, `args`, `ephemeral`, `reads`                             | A step with scope create. No instance exists yet, so instance.\* is out of scope.                                                                                                           |
| `instance-step`       | `/steps/<step>/guards/<i>/expr`<br />`/steps/<step>/bind/accounts/<name>`<br />`/steps/<step>/bind/roles/<role>`<br />`/steps/<step>/fee/asset/mint`<br />`/steps/<step>/glue/atas/<i>/owner`<br />`/steps/<step>/glue/atas/<i>/mint`<br />`/steps/<step>/glue/wrapSol/amount`<br />`/steps/<step>/build/instructions/<i>/args/<name>`<br />`/steps/<step>/build/instructions/<i>/accounts/<name>`<br />`/steps/<step>/build/instructions/<i>/remainingAccounts/<k>/pubkey` | `now`, `deployment`, `wallet`, `instance`                | `params`, `resources`, `args`, `ephemeral`, `reads`                             | A step with scope instance.                                                                                                                                                                 |
| `participant-step`    | `/steps/<step>/guards/<i>/expr`<br />`/steps/<step>/bind/accounts/<name>`<br />`/steps/<step>/bind/roles/<role>`<br />`/steps/<step>/fee/asset/mint`<br />`/steps/<step>/glue/atas/<i>/owner`<br />`/steps/<step>/glue/atas/<i>/mint`<br />`/steps/<step>/glue/wrapSol/amount`<br />`/steps/<step>/build/instructions/<i>/args/<name>`<br />`/steps/<step>/build/instructions/<i>/accounts/<name>`<br />`/steps/<step>/build/instructions/<i>/remainingAccounts/<k>/pubkey` | `now`, `deployment`, `wallet`, `instance`, `participant` | `params`, `resources`, `args`, `ephemeral`, `reads`                             | A step with scope participant.                                                                                                                                                              |
| `instance-machine`    | `/machines/<machine>/derive/<i>/when`<br />`/machines/<machine>/derive/<i>/at`<br />`/reactions/<i>/trigger/time`<br />`/reactions/<i>/trigger/condition`                                                                                                                                                                                                                                                                                                                   | `now`, `deployment`, `instance`                          | `params`, `resources`, `reads`                                                  | Derivations of the instance machine and reactions on it. reads are the machine's reads. No wallet and no args.                                                                              |
| `participant-machine` | `/machines/<machine>/derive/<i>/when`<br />`/machines/<machine>/derive/<i>/at`<br />`/reactions/<i>/trigger/time`<br />`/reactions/<i>/trigger/condition`                                                                                                                                                                                                                                                                                                                   | `now`, `deployment`, `instance`, `participant`, `wallet` | `params`, `resources`, `reads`                                                  | Derivations of the participant machine and reactions on it; wallet is the participant's wallet.                                                                                             |
| `read-address`        | `/reads/<read>/address`                                                                                                                                                                                                                                                                                                                                                                                                                                                     | `deployment`                                             | `params`, `resources`, `wallet`, `args`, `ephemeral`, `instance`, `participant` | Checked once for every step or machine that uses the read, with that user's names minus now and reads. A name must be in scope at every use. A read no step or machine uses is not checked. |
| `squads-multisig`     | `/steps/<step>/authority/multisig`                                                                                                                                                                                                                                                                                                                                                                                                                                          | none                                                     | `resources`                                                                     | A step's names, but the expression may read only resources.\* and literals, and must read at least one resource.                                                                            |

## Limits

Each expression may be at most 2048 bytes, 1024
nodes (literals, names, operators and calls) and 64 levels of nesting.
Over a limit, the check answers `source-limit-exceeded`.

## Not supported

| Instead of                                               | Write                                                                                                                              |
| -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `resources.venues[args.i]` (an index computed from args) | A literal index, `resources.venues[1]`, or `args.venue in resources.venues` to accept any entry, so every address stays reviewable |
| `index(list, 0).field`                                   | `list[0].field`: `index()` returns an untyped value, so no field can follow it                                                     |
| `cond ? a : b`                                           | `if(cond, a, b)`                                                                                                                   |
| `x.len()`, `x.startsWith(y)` (methods)                   | `len(x)`, `starts_with(x, y)`                                                                                                      |
| `-x` on a name                                           | `0 - x` (a leading `-` is only part of a number literal)                                                                           |
| Float math (`1.5 * x`, `pow`)                            | Scaled integer math: `x * 15 / 10`                                                                                                 |
| A PDA the program's IDL does not name                    | Only the IDL's named PDAs: `pda("alias", "name", seeds...)`                                                                        |
| Variables or `let`                                       | Repeat the sub-expression, or derive a machine state from it                                                                       |
| `x ?? y` with a non-literal default                      | A literal default (`x ?? 0`), or `if(exists(x), x, y)`                                                                             |

## Rejections

### Upload and activation

An upload (and the server check) answers with a problem whose `code` names
the stage and whose `errors` list names each failure: `path` (a JSON
pointer into the spec), `code` and `message`.

| Code                                                   | When                                                                                                                          | Fix                                                                    |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
| `protocol-invalid-document`                            | The spec does not match the contract schema. `contractCode` and `path` say where                                              | Rebuild with the current `@usearete/protocol`; fix the field at `path` |
| `protocol-spec-check-failed`                           | An expression failed its check. Each `errors` entry has one of the expression codes below                                     | Fix each entry at its `path`                                           |
| `protocol-template-check-failed`                       | A template does not match the program it calls. Each `errors` entry has one of the template codes below                       | Fix each entry at its `path`                                           |
| `protocol-bundle-mismatch`                             | A handler step without `handlers.mjs`, or a bundle with a template-only spec                                                  | Upload exactly the build's files                                       |
| `protocol-bundle-invalid`, `protocol-bundle-too-large` | The bundle is not canonical base64, or is over the size limit                                                                 | Upload the build's `handlers.mjs`                                      |
| `protocol-template-check-pending`                      | Activation: Arete does not have a program spec a template pins yet. `errors` names each one (`protocol-program-spec-missing`) | Publish or install the program, then activate again                    |
| `protocol-resource-unpublished`                        | Activation: a resource the spec declares has no published version. `errors` names each one                                    | Publish a value for each resource                                      |
| `protocol-fee-policy-missing`                          | Activation: the deployment's fee policy is missing                                                                            | Create the deployment with a fee policy                                |
| `protocol-review-required`                             | Activation of a release with handler code                                                                                     | An operator reviews the release first                                  |
| `plan-capability-required`                             | The account's plan cannot create protocols                                                                                    | See `a4 auth whoami`                                                   |

### Expression codes

| Code                                 | Cause                                                                                                                                                                                               | Fix                                                                                                                                                                             |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid-expression`                 | The expression does not parse, a function got the wrong number of arguments, an argument that must be a literal is not one, or an index is not an integer literal.                                  | Fix the syntax at the reported offset; check the function's arguments in this reference. Index with a literal (resources.venues[1]), or use `in` to accept any value of a list. |
| `index-out-of-range`                 | A literal index is at or past the array's maxItems, so it can never hold a value.                                                                                                                   | Use an index below maxItems, or raise maxItems in the array's schema.                                                                                                           |
| `unknown-reference`                  | A name that is not in scope at this place in the spec.                                                                                                                                              | Check the scope table: declare the arg, read, resource or param, or move the expression to a site where the name exists.                                                        |
| `unsupported-feature`                | A function, operator or character the language does not have, float math in a protocol, or a `??` default that is not a literal.                                                                    | Use a listed function or operator; see what is not supported, with its workaround.                                                                                              |
| `expression-type-mismatch`           | The expression has the wrong type for its place (a guard that is not boolean, an account that is not a public key, a wrap amount that is not an integer) or a function got the wrong argument type. | Compare the message's expected and found types; cast with u64(...), string(...), etc. where a conversion is meant.                                                              |
| `source-limit-exceeded`              | The expression is over a limit: source bytes, nodes or nesting depth.                                                                                                                               | Split the logic: derive a value in a machine state, or move a constant into a resource.                                                                                         |
| `squads-multisig-not-from-resources` | A Squads step's multisig reads something other than resources.\* and literals.                                                                                                                      | Declare the multisig as a resource and use resources.\<name\>.                                                                                                                  |

### Template codes

| Code                            | Cause                                                                                                                       | Fix                                                                                                                                                                                                                     |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `template_program_spec_missing` | The template's program alias is not declared in the spec's programs, so there is no pinned ProgramSpec to check it against. | Declare the program: install it and use its alias, or declare a builtin with builtins(...) (system, splToken, associatedToken, computeBudget, memo). Registry names such as spl-ata map to the builtin associatedToken. |
| `template_unknown_instruction`  | The program's IDL has no instruction with this name.                                                                        | Use the instruction name from the IDL (camelCase and snake_case both match).                                                                                                                                            |
| `template_unknown_arg`          | The template supplies an argument the instruction does not take.                                                            | Remove it, or correct its name to the IDL's.                                                                                                                                                                            |
| `template_missing_arg`          | The template does not supply one of the instruction's arguments.                                                            | Add every IDL argument to the template's args.                                                                                                                                                                          |
| `template_arg_type_mismatch`    | An argument's expression has a type the IDL argument cannot take.                                                           | Cast or change the expression to the IDL type.                                                                                                                                                                          |
| `template_unknown_account`      | The template names an account the instruction does not have.                                                                | Remove it, or correct its name to the IDL's.                                                                                                                                                                            |
| `template_missing_account`      | A required account is neither supplied nor derivable from the IDL (a PDA or a known program address).                       | Supply it in the template's accounts.                                                                                                                                                                                   |

### Prepare and submit

Template codes that appear when a step is prepared:

| Code                         | Cause                                                                                                                 | Fix                                                            |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| `template_unknown_step`      | The step being prepared does not exist.                                                                               | Call a step the deployment's spec declares.                    |
| `template_not_a_template`    | The step builds with a handler, not a template.                                                                       | Internal: report it.                                           |
| `template_evaluation_failed` | An expression failed while building the transaction (a null where a value is needed, an overflow, a missing account). | Read the message; guard against the case in the step's guards. |
| `template_unchecked`         | An expression was not checked at upload.                                                                              | Internal: report it.                                           |
| `template_encode_failed`     | A value does not fit the IDL type when the instruction is encoded (out of range, wrong length).                       | Bound the value with a guard, or cast it to the IDL type.      |

Other prepare and submit answers:

| Code                                        | When                                                                       | Fix                                                                                |
| ------------------------------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `guard_rejected`                            | A guard was false                                                          | The `guard` field names it; check the step's preconditions with `protocol_actions` |
| `instance_terminal`, `participant_terminal` | The instance or the wallet's participant has finished                      | Use another instance                                                               |
| `step_not_client_callable`                  | The step is a keeper or admin step                                         | Keepers and operators run it                                                       |
| `step_requires_secret_key`                  | The step is secret                                                         | Prepare it with a secret-key session                                               |
| `step_scope_mismatch`                       | The step is not prepared on this route (a create step on an instance, say) | Use the route for the step's scope                                                 |
| `protocol-args-invalid`                     | The args do not match the step's args schema                               | Fix the field the message names                                                    |
| `protocol-deployment-inactive`              | The deployment is not active                                               | Activate it                                                                        |
| `transaction-entitlement-required`          | The account cannot use the managed transaction gateway                     | See `a4 auth whoami`                                                               |
| `idempotency_key_conflict`                  | The idempotency key was used for a different request                       | Use a new key                                                                      |
| `execution_intent_expired`                  | The prepared execution expired before submit                               | Prepare it again                                                                   |
