> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/solana-foundation/anchor/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Learn how to define and use custom errors with the error_code macro and error codes in Anchor programs

Proper error handling is crucial for building robust Solana programs. Anchor provides a comprehensive error handling system with custom errors, built-in framework errors, and helpful macros for validation.

## Error Types in Anchor

Anchor errors fall into two main categories:

1. **Framework Errors**: Built-in errors from Anchor (error codes 100-5000)
2. **Custom Errors**: Program-specific errors you define (starting at 6000)

### The Error Enum

Anchor's error type is defined as:

```rust theme={null}
pub enum Error {
    AnchorError(Box<AnchorError>),
    ProgramError(Box<ProgramErrorWithOrigin>),
}
```

## Defining Custom Errors

Use the `#[error_code]` attribute to define custom errors:

```rust theme={null}
#[error_code]
pub enum ErrorCode {
    #[msg("The provided value is too large")]
    ValueTooLarge,
    #[msg("The provided value is too small")]
    ValueTooSmall,
    #[msg("Unauthorized access attempt")]
    Unauthorized,
    #[msg("Insufficient funds for this operation")]
    InsufficientFunds,
}
```

### Error Code Numbers

Custom errors are automatically assigned codes starting from 6000:

```rust theme={null}
ValueTooLarge = 6000
ValueTooSmall = 6001
Unauthorized = 6002
InsufficientFunds = 6003
```

Framework error code ranges:

| Range   | Description          |
| ------- | -------------------- |
| >= 100  | Instruction errors   |
| >= 1000 | IDL errors           |
| >= 2000 | Constraint errors    |
| >= 3000 | Account errors       |
| >= 4100 | Miscellaneous errors |
| >= 6000 | Custom user errors   |

## Returning Errors

### Using err! Macro

The `err!` macro returns an error from your instruction:

```rust theme={null}
pub fn set_value(ctx: Context<SetValue>, value: u64) -> Result<()> {
    if value > 100 {
        return err!(ErrorCode::ValueTooLarge);
    }
    
    ctx.accounts.my_account.value = value;
    Ok(())
}
```

### Using require! Macro

The `require!` macro provides a concise way to validate conditions:

```rust theme={null}
pub fn set_value(ctx: Context<SetValue>, value: u64) -> Result<()> {
    require!(value <= 100, ErrorCode::ValueTooLarge);
    require!(value >= 10, ErrorCode::ValueTooSmall);
    
    ctx.accounts.my_account.value = value;
    Ok(())
}
```

If the condition is false, `require!` returns the specified error.

## Validation Macros

Anchor provides several macros for common validation patterns:

### require!

Ensures a condition is true:

```rust theme={null}
require!(amount > 0, ErrorCode::InvalidAmount);
```

### require\_eq!

Ensures two values are equal:

```rust theme={null}
require_eq!(account.owner, authority.key(), ErrorCode::Unauthorized);
```

### require\_neq!

Ensures two values are not equal:

```rust theme={null}
require_neq!(from.key(), to.key(), ErrorCode::SameAccount);
```

### require\_keys\_eq!

Ensures two Pubkeys are equal:

```rust theme={null}
require_keys_eq!(account.authority, authority.key(), ErrorCode::Unauthorized);
```

### require\_keys\_neq!

Ensures two Pubkeys are not equal:

```rust theme={null}
require_keys_neq!(sender.key(), receiver.key(), ErrorCode::CannotSendToSelf);
```

### require\_gt!

Ensures the first value is greater than the second:

```rust theme={null}
require_gt!(new_amount, old_amount, ErrorCode::AmountNotIncreased);
```

### require\_gte!

Ensures the first value is greater than or equal to the second:

```rust theme={null}
require_gte!(balance, amount, ErrorCode::InsufficientFunds);
```

## Complete Example

Here's a comprehensive example demonstrating error handling:

```rust theme={null}
use anchor_lang::prelude::*;

declare_id!("Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS");

#[program]
pub mod vault {
    use super::*;

    pub fn initialize(ctx: Context<Initialize>, max_amount: u64) -> Result<()> {
        require!(max_amount > 0, ErrorCode::InvalidMaxAmount);
        
        let vault = &mut ctx.accounts.vault;
        vault.authority = ctx.accounts.authority.key();
        vault.balance = 0;
        vault.max_amount = max_amount;
        
        msg!("Vault initialized with max amount: {}", max_amount);
        Ok(())
    }

    pub fn deposit(ctx: Context<Deposit>, amount: u64) -> Result<()> {
        require!(amount > 0, ErrorCode::InvalidAmount);
        
        let vault = &mut ctx.accounts.vault;
        let new_balance = vault.balance
            .checked_add(amount)
            .ok_or(ErrorCode::Overflow)?;
        
        require!(new_balance <= vault.max_amount, ErrorCode::ExceedsMaxAmount);
        
        vault.balance = new_balance;
        msg!("Deposited {}. New balance: {}", amount, vault.balance);
        Ok(())
    }

    pub fn withdraw(
        ctx: Context<Withdraw>,
        amount: u64,
    ) -> Result<()> {
        require!(amount > 0, ErrorCode::InvalidAmount);
        require_gte!(ctx.accounts.vault.balance, amount, ErrorCode::InsufficientFunds);
        
        let vault = &mut ctx.accounts.vault;
        vault.balance = vault.balance
            .checked_sub(amount)
            .ok_or(ErrorCode::Underflow)?;
        
        msg!("Withdrew {}. Remaining balance: {}", amount, vault.balance);
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(
        init,
        payer = authority,
        space = 8 + Vault::INIT_SPACE
    )]
    pub vault: Account<'info, Vault>,
    #[account(mut)]
    pub authority: Signer<'info>,
    pub system_program: Program<'info, System>,
}

#[derive(Accounts)]
pub struct Deposit<'info> {
    #[account(mut)]
    pub vault: Account<'info, Vault>,
}

#[derive(Accounts)]
pub struct Withdraw<'info> {
    #[account(
        mut,
        has_one = authority @ ErrorCode::Unauthorized
    )]
    pub vault: Account<'info, Vault>,
    pub authority: Signer<'info>,
}

#[account]
#[derive(InitSpace)]
pub struct Vault {
    pub authority: Pubkey,
    pub balance: u64,
    pub max_amount: u64,
}

#[error_code]
pub enum ErrorCode {
    #[msg("Amount must be greater than zero")]
    InvalidAmount,
    #[msg("Max amount must be greater than zero")]
    InvalidMaxAmount,
    #[msg("Insufficient funds in vault")]
    InsufficientFunds,
    #[msg("Deposit would exceed maximum vault amount")]
    ExceedsMaxAmount,
    #[msg("Only the authority can perform this action")]
    Unauthorized,
    #[msg("Arithmetic overflow occurred")]
    Overflow,
    #[msg("Arithmetic underflow occurred")]
    Underflow,
}
```

## Error Responses

When an error occurs, Anchor provides detailed information in the transaction logs:

```
Program log: AnchorError thrown in programs/vault/src/lib.rs:25. 
  Error Code: InsufficientFunds. 
  Error Number: 6002. 
  Error Message: Insufficient funds in vault.
```

### Client-Side Error Handling

In TypeScript clients, catch and handle errors:

```typescript theme={null}
try {
  await program.methods
    .withdraw(new anchor.BN(1000))
    .accounts({ vault, authority })
    .rpc();
} catch (error) {
  if (error.error.errorCode.code === 'InsufficientFunds') {
    console.log('Not enough funds in vault');
    console.log('Error message:', error.error.errorMessage);
  }
}
```

Error response structure:

```javascript theme={null}
{
  error: {
    errorCode: { code: 'InsufficientFunds', number: 6002 },
    errorMessage: 'Insufficient funds in vault',
    origin: { file: 'programs/vault/src/lib.rs', line: 25 }
  },
  logs: [...],
  errorLogs: [...]
}
```

## Common Framework Errors

Some frequently encountered Anchor framework errors:

| Error                 | Code | Description                  |
| --------------------- | ---- | ---------------------------- |
| ConstraintMut         | 2000 | Account should be mutable    |
| ConstraintHasOne      | 2001 | has\_one constraint violated |
| ConstraintSigner      | 2002 | Account should be a signer   |
| ConstraintOwner       | 2004 | Wrong account owner          |
| ConstraintSeeds       | 2006 | PDA seeds don't match        |
| AccountNotInitialized | 3012 | Account not initialized      |
| RequireViolated       | 2500 | require! condition failed    |

## Best Practices

1. **Use descriptive error messages**: Make errors easy to understand and debug
2. **Validate early**: Check conditions at the start of instructions
3. **Use specific errors**: Create distinct error codes for different failure cases
4. **Leverage constraints**: Use account constraints for validation when possible
5. **Check arithmetic**: Use checked operations to prevent overflows
6. **Document errors**: Add comments explaining when each error is used
7. **Test error cases**: Write tests that verify error conditions

## Using Constraints for Validation

Many validations can be done with account constraints instead of manual checks:

```rust theme={null}
#[derive(Accounts)]
pub struct Withdraw<'info> {
    #[account(
        mut,
        has_one = authority @ ErrorCode::Unauthorized,
        constraint = vault.balance >= amount @ ErrorCode::InsufficientFunds
    )]
    pub vault: Account<'info, Vault>,
    pub authority: Signer<'info>,
}
```

This approach is more concise and errors are caught during account validation.

## Related Resources

* [Anchor Error Source Code](https://github.com/coral-xyz/anchor/blob/master/lang/src/error.rs)
* [Error Test Examples](https://github.com/coral-xyz/anchor/blob/master/tests/errors/programs/errors/src/lib.rs)
* [Account Constraints Reference](/api/rust/account-constraints)
