Skip to main content
Sigvex

Improper Error Handling Remediation

How to fix silently ignored errors and improper error propagation.

Improper Error Handling Remediation

Overview

Related Detector: Improper Error Handling

Silently discarded errors allow programs to continue with invalid assumptions, potentially leading to fund loss or state corruption. The fix is to propagate all errors from CPI calls, syscalls, and deserialization using Rust’s ? operator, and to handle error cases explicitly when custom recovery logic is needed.

Before (Vulnerable)

use solana_program::program::invoke;

// Vulnerable: ignoring CPI result
pub fn withdraw(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    let ix = spl_token::instruction::transfer(
        &spl_token::id(), &source, &dest, &authority, &[], amount
    )?;
    let _ = invoke(&ix, accounts);  // Silent failure
    mark_withdrawn(accounts, amount)?;
    Ok(())
}

After (Fixed)

use solana_program::program::invoke;

// Fixed: propagate all errors
pub fn withdraw(accounts: &[AccountInfo], amount: u64) -> ProgramResult {
    let ix = spl_token::instruction::transfer(
        &spl_token::id(), &source, &dest, &authority, &[], amount
    )?;
    invoke(&ix, accounts)?;  // Failure stops execution
    mark_withdrawn(accounts, amount)?;
    Ok(())
}

Alternative Mitigations

Custom Error Recovery

When you need to handle specific error cases rather than propagating directly:

match invoke(&ix, accounts) {
    Ok(()) => {
        mark_withdrawn(accounts, amount)?;
    }
    Err(e) => {
        msg!("Transfer failed: {:?}", e);
        return Err(e);  // Always propagate or return an error
    }
}

Common Mistakes

Mistake: Logging Without Propagating

// WRONG: logs the error but continues execution
if let Err(e) = invoke(&ix, accounts) {
    msg!("Warning: transfer failed: {:?}", e);
}
// Program continues as if transfer succeeded

Mistake: Mapping to Ok

// WRONG: converts error to success
let _result = invoke(&ix, accounts).unwrap_or(());

Always ensure errors from state-changing operations halt further state modifications.

References