The #[account] Constraints
Field attributes on accounts struct members compose validation rules. Anchor evaluates them in a defined order before your instruction handler runs.
Search across all documentation pages
Field attributes on accounts struct members compose validation rules. Anchor evaluates them in a defined order before your instruction handler runs.
#[account(
mut,
has_one = authority,
constraint = vault.amount > 0 @ MyError::InvalidAmount,
)]
pub vault: Account<'info, Vault>,Constraint expressions may reference only sibling account fields and instruction arguments declared with #[instruction(...)]. A bare amount here would not compile; if it really is an instruction argument, add #[instruction(amount: u64)] to the struct.
When to reach for this: You express ownership, relationships, or custom invariants declaratively.
#[derive(Accounts)]
#[instruction(new_fee_bps: u16)]
pub struct SetFee<'info> {
#[account(
mut,
seeds = [b"config"],
bump = config.bump,
has_one = admin,
constraint = new_fee_bps <= 10_000 @ ConfigError::FeeTooHigh,
)]
pub config: Account<'info, Config>,
pub admin: Signer<'info>,
}What this demonstrates:
#[instruction(...)] brings the handler's arguments into constraint scope; it must list them in order, starting from the firstmut marks writable accountshas_one checks pubkey equality to nested fieldconstraint runs arbitrary boolean expressions@ maps to custom error enum variant| Attribute | Purpose |
|---|---|
mut | Account is writable |
signer | Must be signer (on non-Signer types) |
has_one = field | Account field equals other account key |
address = expr | Exact pubkey match |
owner = prog | Owner program check |
constraint = expr | Custom invariant |
Combine attributes; all must pass.
@ MyError::Variant for clarity.pubkey! constants per cluster feature flags.mut on accounts you persist.| Alternative | Use When | Don't Use When |
|---|---|---|
| require! in handler | Dynamic logic across accounts | Static relationship checks |
| Custom constraint tokens (0.32) | Reusable patterns | One-off simple rules |
| Manual native checks | No Anchor | You use Anchor for safety |
0.32.1 for anchor-lang, Anchor CLI, and examples in this section.
Yes. Solana CLI 3.0.10 handles keypairs, airdrops, and solana program inspection.
target/idl/<program>.json in your workspace.
Yes, but every unchecked field needs explicit constraints or handler checks.
Use anchor test with Surfpool 0.12.0 or LiteSVM 0.6.x in CI.
Anchor account discriminator; do not strip it when sizing space.
Yes, or publish on-chain IDL so clients have a canonical source.
Run with logs; Anchor prints constraint name and account index.
Yes. This stack targets Agave validators with Solana CLI 3.0.10.
See sibling articles linked in Related for deeper account constraints topics.
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.
Reviewed by Chris St. John·Last updated Jul 16, 2026