Error Handling Basics
10 examples to get you started with Errors & Logs - 7 basic and 3 intermediate.
Prerequisites
- Instruction handlers return
ProgramResultfrom Rust for Solana.
Basic Examples
1. ProgramResult
Instructions return Result<(), ProgramError>.
use solana_program::entrypoint::ProgramResult;
pub fn handler() -> ProgramResult { Ok(()) }- Err fails the entire transaction.
- Ok commits state atomically with other ix.
- Use
?in helpers.
2. Built-in errors
Runtime provides standard error codes.
return Err(ProgramError::InvalidArgument);- Portable across programs.
- Limited expressiveness for UX.
- Good for internal invariant failures.
3. Custom error code
Domain-specific u32 codes.
return Err(ProgramError::Custom(6001));- Clients map to messages.
- Document per program.
- Anchor offsets auto in IDL.
4. Map from enum
thiserror-style From impl.
impl From<MyError> for ProgramError {
fn from(e: MyError) -> Self { ProgramError::Custom(e as u32) }
}- Enables
?ergonomics. - Keep codes stable.
- Export enum for SDK.
5. No panic
Never unwrap user input paths.
// BAD: data[0]; // GOOD: data.get(0).ok_or(...)?- Panic aborts instruction.
- Return typed errors.
- Fuzz to find panics.
6. CPI errors
Bubble callee failures.
invoke(&ix, accounts)?;- ? propagates ProgramError.
- Map if you need custom code.
- Logs may show inner program.
7. Client sees
Failed tx with code in metadata.
// off-chain: parse logs + err code- Simulation preview same codes.
- Wallets show generic failure.
- Your dApp maps custom codes.
Intermediate Examples
8. Anchor errors
error_code attribute in 0.32.1.
#[error_code]
pub enum Error { InsufficientFunds }- Auto IDL export.
- Offset from 6000.
- Compatible with @solana/kit decoders.
Related: Custom Error Enums
9. Log on error path
Short msg for debug - mind CU.
solana_program::msg!("reject: insufficient");- Public logs - no secrets.
- Prefer custom error for UX.
- Strip in production hot paths.
Related: Logging with msg!
10. Decode off-chain
Match Custom code to enum.
// TS: parse simulation err- IDL gives name mapping.
- Native needs published table.
- Anchor lang 0.32.1 IDL JSON.
Related: Decoding Errors Off-Chain
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.