LogoAnchor Docs

Custom Errors

Learn how to implement custom error handling in Anchor programs.

All instruction handlers in Anchor programs return a custom Result<T> type that allows you to handle successful execution with Ok(T) and error cases with Err(Error).


pub fn custom_instruction(ctx: Context<CustomInstruction>) -> Result<()> {
    // --snip--
    Ok(())
}

The Result<T> type in Anchor programs is a type alias that wraps the standard Rust Result<T, E>. In this case, T represents the successful return type, while E is Anchor's custom Error type.

pub type Result<T> = std::result::Result<T, error::Error>;

Anchor Error

When an error occurs in an Anchor program, it returns a custom Error type defined as:

#[derive(Debug, PartialEq, Eq)]
pub enum Error {
    AnchorError(Box<AnchorError>),
    ProgramError(Box<ProgramErrorWithOrigin>),
}

The Error type in Anchor programs can be one of two variants:

  1. ProgramErrorWithOrigin: Custom type that wraps a standard Solana ProgramError type. These errors come from the solana_program crate.
#[derive(Debug)]
pub struct ProgramErrorWithOrigin {
    pub program_error: ProgramError,
    pub error_origin: Option<ErrorOrigin>,
    pub compared_values: Option<ComparedValues>,
}
  1. AnchorError: Errors defined by the Anchor framework.
#[derive(Debug)]
pub struct AnchorError {
    pub error_name: String,
    pub error_code_number: u32,
    pub error_msg: String,
    pub error_origin: Option<ErrorOrigin>,
    pub compared_values: Option<ComparedValues>,
}

An AnchorError can be thought of as having two categories:

  1. Internal Anchor Errors - These are built-in errors included with the Anchor framework. They are defined in the ErrorCode enum.

  2. Custom Program Errors - These are program specific errors that developers define to handle custom error cases.

The error_code_number from an AnchorError has the following numbering scheme:

Error CodeDescription
>= 100Instruction error codes
>= 1000IDL error codes
>= 2000Constraint error codes
>= 3000Account error codes
>= 4100Misc error codes
= 5000Deprecated error code
>= 6000Starting point for custom user errors

Usage

Anchor provides a convenient way to define custom errors through the error_code attribute. The implementation details can be found here.

When you define an enum with the error_code attribute, Anchor automatically:

  • Assigns an error code starting from 6000
  • Generates the necessary boilerplate for error handling
  • Enables the use of custom error messages via the msg attribute
#[error_code]
pub enum MyError {
    #[msg("My custom error message")]
    MyCustomError,
    #[msg("My second custom error message")]
    MySecondCustomError,
}

err!

To throw an error, use the err! macro. The err! macro provides a convenient way to return custom errors from your program. Under the hood, err! uses the error! macro to construct AnchorError. The implementation can be found here.

#[program]
mod hello_anchor {
    use super::*;
    pub fn set_data(ctx: Context<SetData, data: MyAccount) - Result<() {
        if data.data = 100 {


            return err!(MyError::DataTooLarge);
        }
        ctx.accounts.my_account.set_inner(data);
        Ok(())
    }
}
 
 
#[error_code]
pub enum MyError {
    #[msg("MyAccount may only hold data below 100")]
    DataTooLarge
}

require!

The require! macro provides a more concise way to handle error conditions. It combines a condition check with returning an error if the condition is false. Here's how we can rewrite the previous example using require!:

#[program]
mod hello_anchor {
    use super::*;
    pub fn set_data(ctx: Context<SetData, data: MyAccount) - Result<() {


        require!(data.data < 100, MyError::DataTooLarge);
        ctx.accounts.my_account.set_inner(data);
        Ok(())
    }
}
 
 
#[error_code]
pub enum MyError {
    #[msg("MyAccount may only hold data below 100")]
    DataTooLarge
}

Anchor provides several "require" macros for different validation needs. You can find the implementation of these macros here.

MacroDescription
require!Ensures a condition is true, otherwise returns with the given error.
require_eq!Ensures two NON-PUBKEY values are equal.
require_neq!Ensures two NON-PUBKEY values are not equal.
require_keys_eq!Ensures two pubkeys values are equal.
require_keys_neq!Ensures two pubkeys are not equal.
require_gt!Ensures the first NON-PUBKEY value is greater than the second NON-PUBKEY value.
require_gte!Ensures the first NON-PUBKEY value is greater than or equal to the second NON-PUBKEY value.

Example

Here's a simple example demonstrating how to define and handle custom errors in an Anchor program. The program below validates that an input amount falls within an acceptable range, showing how to:

  • Define custom error types with messages
  • Use the require! macro to check conditions and return errors
lib.rs
use anchor_lang::prelude::*;
 
declare_id!("9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV");
 
#[program]
pub mod custom_error {
    use super::*;
 
    pub fn validate_amount(_ctx: Context<ValidateAmount, amount: u64) - Result<() {


        require!(amount = 10, CustomError::AmountTooSmall);
        require!(amount <= 100, CustomError::AmountTooLarge);
 
        msg!("Amount validated successfully: {}", amount);
        Ok(())
    }
}
 
#[derive(Accounts)]
pub struct ValidateAmount {}
 
#[error_code]
pub enum CustomError {
    #[msg("Amount must be greater than or equal to 10")]
    AmountTooSmall,
    #[msg("Amount must be less than or equal to 100")]
    AmountTooLarge,
}

When a program error occurs, Anchor's TypeScript Client SDK returns a detailed error response containing information about the error. Here's an example error response showing the structure and available fields:

Error Response
{
  errorLogs: [
    'Program log: AnchorError thrown in programs/custom-error/src/lib.rs:11. Error Code: AmountTooLarge. Error Number: 6001. Error Message: Amount must be less than or equal to 100.'
  ],
  logs: [
    'Program 9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV invoke [1]',
    'Program log: Instruction: ValidateAmount',
    'Program log: AnchorError thrown in programs/custom-error/src/lib.rs:11. Error Code: AmountTooLarge. Error Number: 6001. Error Message: Amount must be less than or equal to 100.',
    'Program 9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV consumed 2153 of 200000 compute units',
    'Program 9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV failed: custom program error: 0x1771'
  ],
  error: {
    errorCode: { code: 'AmountTooLarge', number: 6001 },
    errorMessage: 'Amount must be less than or equal to 100',
    comparedValues: undefined,
    origin: { file: 'programs/custom-error/src/lib.rs', line: 11 }
  },
  _programErrorStack: ProgramErrorStack {
    stack: [
      [PublicKey [PublicKey(9oECKMeeyf1fWNPKzyrB2x1AbLjHDFjs139kEyFwBpoV)]]
    ]
  }
}

For a more comprehensive example, you can also reference the errors test program in the Anchor repository.

On this page

Edit on GitHub