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

Validation Rules

The transpiler reports diagnostics with short codes. Errors stop code generation (exit code 1); warnings do not. Run cambrian-transpiler <file.cam> --check (or --project p.yaml --check) to see them without writing output; --diagnostic-format json gives machine-readable output. The authoritative source is cambrian-transpiler/src/validate/. This page lists the codes that apply to the public targets (--target evm, --target lean).

Families

PrefixConcern
VEntity / route / member / phase / deploy / match
EEVM / Solidity compatibility
LLean target
Ttest / property / fuzz
Iinvariant
Fproject.yaml / imports
WWarnings / lints

Unless marked (warning), a code is an error. Codes tagged EVM fire for both --target evm and --target lean (both model the EVM); Solidity codes fire only for --target evm; Lean codes only for --target lean.

V — entities, routes, members

CodeSummary
V1Member transform in <route> names an unknown route
V2(warning) Route has no member transforms and an empty body
V3Unknown ^member, or a temporal cycle between members in one route
V4pure fn or library function reads an entity member, msg::*, sys::*, temporals, macros or impure evm::* (pass the value as a parameter)
V7Constant value is not a literal
V8Undefined identifier, function, macro or temporal reference
V9view route has member transforms, or (transitively) calls a route that has member transforms or state-changing actions
V10pure route has member transforms
V11pure route uses an impure construct (msg::*, sys::*, members, sends, deploys, call, …)
V12More than one init route, or an init route with a return type
V13Duplicate phase name
V14Unphased transform on a phased route, or phased transform on an unphased route
V15Transform references an unknown phase
V16 / V17identity member declares transforms / a default value
V20Empty string "" compared with an address
V22ns::name(...) without the matching use import — often a send misspelt as Entity::route(args) ~> dest (write route(args) ~> dest)
V23Named send or var capture to an untyped address (type the destination Address<E> or declare an extern entity), or to a route the target entity doesn’t declare
V24var x = r(...) ~> dest targets a route with no return type
V25var shadows a parameter or member, or is defined twice
V26var used in a member transform of the same or an earlier phase (or an unphased route)
V27Route-level where references a var defined in the body
V28Per-phase where references a var from the same or a later phase
V29Forbidden action inside an action-level for (var capture, return)
V30 / V31Duplicate extern entity (or clash with an entity) / duplicate extern route
V32deploy E(args) arity ≠ identity members + init-route params
V33EVM — from E(args) arity ≠ identity-member count of E
V34 / V35emit of an undeclared event / wrong arity or types
V36EVM — event with more than three indexed parameters
V38 / V39throw Name of an undeclared error / wrong arity or types
V40 / V41EVM — receive / fallback wrong shape (no params, no return, not view/pure; receive needs accept) / declared twice
V42return(value) in a route without -> T (bare return is fine)
V43^member outside a member transform body
V45Several deploy of the same entity in one route: warning when arguments differ, error when two are identical (address collision)
V47(warning) Unreachable match arm: after _ / a bare identifier, a duplicate arm, or a catch-all after arms that already cover every case (Lean drops that catch-all). Also an error for duplicate names inside a library
V48if without else where a value is required
V49Bare stdlib call (min, pow, sha256, …) without the std::math:: / std::str:: / std::crypto:: prefix
V50Transform assigns an incompatible type (string ↔ number needs std::str::parse_* / format; address vs Address<E>)
V51Unused let in a route or pure fn body
V52Record cycle without Option / Vec / HashMap indirection, or a type alias that never unfolds
V53Nested pattern in let some(<pat>) (use an identifier or _)
V54Route body mixes phase blocks and bare actions
V55using method name collides with a built-in method of the receiver type
V56using names an undeclared pure fn or library
V57using function’s first parameter type doesn’t match the for type
V58Invariant deploy { … } must contain exactly one address
V59deploy { … } on a multi-entity invariant
V60Several from alternatives with different : throw annotations
V62EVM — init/constructor route reads msg::sender (under factory deploy it is the factory); pass the recipient as a constructor parameter. Warning in single-file mode, error with --project
V63EVM — init/constructor route lacks #[factory_only]. Warning in single-file mode, error with --project
V64#[factory_only] on a route other than the init/constructor route
V65Arithmetic (+ - * / %, wrapping variants) on an Option<_> operand
V66Non-exhaustive match without a _ / binding arm: a missing enum variant, some / none, true / false, or integer-literal arms with no catch-all
V67Route or pure fn with -> T never returns a value (and never throws), or returns a value of a different category (numeric / String / bool)
V68Record literal R { … } sets a field twice, names an unknown field, or omits a field (use base { field: v } to update an existing value)
V69Signed and unsigned operands with no common signed type: arithmetic mixing a signed operand with u128 / U256, or a comparison with U256; cast one side with as
V70Member transform in r(a, b) binds a different number of parameters than route r declares; bind all (_ for unused ones) or none (in r())

E — EVM / Solidity

CodeSummary
E05(warning) accept on a regular route has no EVM meaning (payability is inferred); accept receive() is exempt
E07Solidity — error for a closure as a value or a bare range outside for; warning for an unsupported iterator chain inside for / .fold
E08(warning) Solidity — enum variant with payload lowers to a tagged-union struct
E09(warning) EVM — from lowers to a msg.sender comparison
E16EVM — namespace call with no EVM lowering (including an unknown evm:: intrinsic name or msg:: field), or encode<…>(…) outside tests
E17Solidity — unrecognised HashMap transform shape; use m.insert / m.update / m.remove (optionally inside if / block / let)
E18Solidity — tuple type outside a multi-return position; use a record
E19Solidity — generic type other than Vec / HashMap / Option
E20Solidity — type name that is not a primitive, record, enum or alias
E21Solidity — unsupported as target (allowed: u8–U256, i8–i128, bool, address, pubkey)
E22EVM — typed send to an entity that is neither in the program nor an extern entity
E23Solidity — mixed-type tuple destructure whose slot types can’t be inferred
E25EVM — std::* call outside the standard-library allowlist
E27Reported after codegen (not by --check): an expression had no EVM lowering and was replaced by 0 in the generated Solidity. The generated files stay on disk for inspection, but the exit code is 1
E28EVM — method with no Solidity or Lean lowering: Option .unwrap() / .unwrap_or() / .expect() / .is_some() / .is_none(), collection .get() / .set(). Use match / let some(x) = …, m[k], or a transform
E29Solidity — view route body contains a send, value transfer, deploy or emit (Lean accepts them)

L — Lean

CodeSummary
L1Generic type other than Vec / HashMap / Option
L2Closure as a value, or unsupported fold accumulator
L5expect throw N on a route that can never fail (vacuous theorem)
L6expect return … on a route without a return type
L7(warning) skip from is not honoured on Lean; from checks stay
L8Typed send whose destination doesn’t statically resolve to an in-program entity
L9var capture of a failing self-call from a route that can’t fail itself (add where / throw)
L10(warning) Invariant action route contains a send; Lean models the route as one atomic step
L11Fire-and-forget self-send to a failing route from a route that can’t fail
L13std::crypto::* (e.g. sha256) has no Lean lowering
L14Type name that is not a primitive, record, enum or alias
L15Unrecognised HashMap transform shape (Lean mirror of E17)
L16Namespaced call or msg:: / sys:: field with no Lean lowering (e.g. std::math::muldivmod, an unknown evm:: name)

T — tests, properties, fuzz

CodeSummary
T1for Entity names an unknown entity
T2 / T3call of an unknown route / wrong arity
T4with { … } / expect state { … } names a non-member field
T5expect before any call
T6Test with no call
T8(warning) Unknown context-block namespace (known: msg, sys)
T10Property parameter collides with a member, or a let shadows a parameter
T11bound in a property body, bad instance binding, or bound / assume in a plain test
T12assume expression is not boolean, or used in a plain test
T15skip if outside an invariant action body
T16advanceTime(...) outside an invariant action body (needs #[with_time])
T17Instance binding shape: test needs p: value, fuzz needs p in lo..hi
T18test instance doesn’t bind every property parameter
T19field: * names a non-member
T20Unknown name in ctx { … } (allowed: msg::{sender,value}, sys::{now,timestamp,chainid,block_number,balance})
T21Field both pinned and * in the same with { … }
T22msg:: / sys:: field in with { … } / init { … } instead of ctx { … }
T23Context parameter declared twice in one ctx { … }
T24Test deploy b = E(...) names an unknown entity
T25Test deploy binding name already in use
T26Test deploy constructor arity mismatch
T27Test deploy initial state names a non-member
T28call b.route(...) on a name not bound by an earlier deploy
T29call b.route(...): unknown route or wrong arity
T30Duplicate test let, let shadowing a parameter, or let x: T with a non-assignable initializer
T31Empty fuzz range for a parameter
T36expect emit in a property (only allowed in test)
T38Boolean expect that isn’t boolean-shaped, or mentions result after a route with no return type / when result is already a name in scope
T39Solidity — expect state on a member with no public Solidity getter (a Vec, a record holding a Vec / HashMap, or a map to Vec); assert through a view route and expect return

I — invariants

CodeSummary
I1action names an unknown route
I2action parameters don’t match the route (arity error; type mismatch is a warning)
I3check is not boolean
I4Forbidden statement in an action body (only bound / assume / skip if / advanceTime)
I5Invariant needs at least one action and one check
I6deploy { … } / senders { … } entry is not an address literal or constant
I8Duplicate instance name
I9Unknown instance entity, or action inst.route on an undeclared instance
I10init inst { … } names a non-member
I11Unqualified member in a multi-entity invariant (write inst.member)
I12derived body contains something other than let
I13Duplicate track name
I14exclude selectors { … } names an undeclared action
I15trace::* names an undeclared action or unknown accessor (length / count / lastWas)
I16trace::* outside an invariant assume / check
I17Solidity — check expression can’t be lowered for Foundry; move the logic into a view route
I18EVM — multi-instance invariant: several instances of an entity without identity members, duplicate identity values, or a cyclic deploy order

F — project configuration and imports

CodeSummary
F2Unknown lean.numerics value (expected overflow-wrap, overflow-panic, nat) or lean.intrinsics value (expected opaque, executable)
F4Imported file (import "…" or yaml imports:) declares entity / test / fuzz / invariant — list it under sources:
F5yaml imports: path or bare import "…" not found next to the importer or in any library_paths root
F6target: evm project that disables the CREATE2 factory deploy (on EVM, entities are always deployed via CREATE2 through the generated CambrianFactory)
F7(warning) Unknown project.yaml key (ignored), or fuzz.shrink (accepted, no effect)

Loader failures use named codes instead: PKG_IO (missing file), PKG_YAML (malformed YAML, missing target / sources, unknown target), PKG_MERGE (conflicting declarations across files), and PARSE_UNEXPECTED_TOKEN (syntax errors).

W — warnings

CodeSummary
W1Member has no transforms
W2pure fn is never called
W3Entity constant is never used
W4Duplicate use import
W5deploy of an entity not defined in the program
W7Fuzz parameter type uses a fallback strategy on this target
W8test instance leaves a field: * unpinned (falls back to the default); also a file imported twice
W9Entity-local record / enum / type shadows a program-scope one (they are distinct types)
W10EVM — route updates a balance/allowance-like member without an emit
W11In a test, call of the init route is followed by msg { sender: … }; set the sender first
W13Invariant bootstraps the constructor without an explicit deploy { … }
W14Invariant deploy address is also listed in senders
W15Invariant check pins member == const while an action can decrease that member (likely vacuous)