Solana for Developers

Creating Custom Errors

Learn how to create custom errors for your program

In the counter program, you used errors provided by solana_program's ProgramError enum that provides comprehensive but somewhat generic errors. These errors may work for some programs; however, some programs, for example, this voting program, may require more specific errors.

For example, you cannot use ProgramError::InvalidInstructionData to handle scenarios where the voting window is closed or when the client passes less than 2 poll options, you need more descriptive errors.

To create custom errors, define a program-specific error enum and convert it to ProgramError so you can return precise failures from your instructions.

Like so:

src/errors.rs
use num_enum::TryFromPrimitive;
use solana_program::program_error::ProgramError;
use solana_program_error::ToStr;
use thiserror::Error;

#[repr(u32)]
#[derive(Debug, Error, Clone, Copy, Eq, PartialEq, TryFromPrimitive)]
pub enum PollError {
    #[error("You need at least 2 poll options")]
    NotEnoughPollOptions = 6000,

    #[error("End Slot cannot be less than start slot")]
    InvalidSlotTime = 6001,

    #[error("Voting window for this poll has closed")]
    VotingWindowClosed = 6002,

    #[error("Voting window for this poll is still open")]
    VotingWindowStillOpen = 6003,

    #[error("This poll has been closed")]
    PollAlreadyClosed = 6004,

    #[error("Input data exceeds max length")]
    InvalidDataLength = 6005,
}

impl From<PollError> for ProgramError {
    fn from(e: PollError) -> Self {
        ProgramError::Custom(e as u32)
    }
}

// Provide a static string for each variant (used by ProgramError::to_str::<PollError>())
impl ToStr for PollError {
    fn to_str(&self) -> &'static str {
        match self {
            Self::NotEnoughPollOptions => "You need at least 2 poll options",
            Self::InvalidSlotTime => "End Slot cannot be less than start slot",
            Self::VotingWindowClosed => "Voting window for this poll has closed",
            Self::VotingWindowStillOpen => "Voting window for this poll is still open",
            Self::PollAlreadyClosed => "This poll has been closed",
            Self::InvalidDataLength => "Input data exceeds max length",
        }
    }
}

Identify your error codes with large numbers to avoid clashes with other packages. For example, Solana's error code for insufficient balance is Custom(1).

thiserror::Error gives each variant a readable message for logs and tests. Now you can use this enum as you’d ProgramError.

Last updated on

On this page

No Headings
Edit on GitHub