Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Custom Errors

Named error declarations describe typed failure ABIs. On EVM they lower to Solidity custom errors and are the preferred way to fail a route, a where guard, or a from check.

Declaration

Errors may appear at program scope or entity scope:

error InsufficientBalance(have: U256, need: U256);

entity Vault {
    error Unauthorized();

    routes {
        withdraw(amount: U256)
            from Owner(m_owner) : throw Unauthorized()
            where m_balance >= amount : throw InsufficientBalance(m_balance, amount)
        => [
            ~> msg::sender with { value: amount }
        ]

        kill()
            from Owner(m_owner) : throw Unauthorized()
        => [
            throw Unauthorized()
        ]
    }
}

Raising errors

FormWhere
: throw ErrorName(args)After a where condition or a from clause
throw ErrorName(args)As a terminator action in a route body

throw / throw Name(...) is a terminator: later actions in the same route (or phase) do not run.

Validation

RuleCode
Error must be declared at program or entity scopeV38
Argument arity / types must matchV39

EVM lowering

CambrianSolidity
error Name(...);error Name(...);
throw Name(args) / : throw Name(args)revert Name(args);

Named vs numeric throw

Older sources may still use a numeric form (: throw 100). Prefer named errors for new code on EVM: they produce typed custom errors that tools and callers can decode. Numeric throw N remains accepted for compatibility and lowers to a string-style revert, but it is not the preferred EVM story.