Skip to main content
The NullGraph program defines 6 custom errors to handle validation failures and prevent invalid state transitions. All errors are defined in the NullGraphError enum using Anchor’s #[error_code] macro. Location: lib.rs:579-593

Error Code Enum

#[error_code]
pub enum NullGraphError {
    #[msg("Bounty is not in the expected status")]
    InvalidBountyStatus,
    #[msg("Submission is not in the expected status")]
    InvalidSubmissionStatus,
    #[msg("Matched submission mismatch")]
    SubmissionMismatch,
    #[msg("Bounty deadline has passed")]
    BountyExpired,
    #[msg("Reward amount must be > 0")]
    InvalidRewardAmount,
    #[msg("Fee calculation overflow")]
    FeeOverflow,
}

InvalidBountyStatus

Code
6000
Message
string
“Bounty is not in the expected status”

Description

Thrown when an instruction attempts to operate on a bounty that is not in the required status.

Thrown By

Status Reference

StatusValueDescriptionValid Operations
Open0Accepting submissionssubmit_to_bounty, close_bounty
Matched1Submission linkedapprove_bounty_submission, close_bounty
Fulfilled2Payout completeNone (terminal state)
Closed3RefundedNone (terminal state)

Code Reference

// submit_to_bounty validation (line 125)
let bounty_status = ctx.accounts.bounty.status;
require!(bounty_status == 0, NullGraphError::InvalidBountyStatus); // Must be Open

// approve_bounty_submission validation (line 157)
require!(bounty.status == 1, NullGraphError::InvalidBountyStatus); // Must be Matched

// close_bounty validation (lines 233-236)
require!(
    bounty.status == 0 || bounty.status == 1,
    NullGraphError::InvalidBountyStatus
);

InvalidSubmissionStatus

Code
6001
Message
string
“Submission is not in the expected status”

Description

Thrown when attempting to approve a submission that is not in Pending status.

Thrown By

Submission Status Reference

StatusValueDescription
Pending0Awaiting creator review
Approved1Accepted, payout executed
Rejected2Declined (not currently used)

Code Reference

// approve_bounty_submission validation (line 164)
let submission = &mut ctx.accounts.submission;
require!(submission.status == 0, NullGraphError::InvalidSubmissionStatus); // Must be Pending

SubmissionMismatch

Code
6002
Message
string
“Matched submission mismatch”

Description

Thrown when the provided BountySubmission account does not match the bounty’s recorded matched_submission field.

Thrown By

Security Note

This check prevents a malicious actor from substituting a different submission during approval. The bounty’s matched_submission field is set atomically in submit_to_bounty and cannot be changed except by approving or closing the bounty.

Code Reference

// approve_bounty_submission validation (lines 158-161)
require!(
    bounty.matched_submission == ctx.accounts.submission.key(),
    NullGraphError::SubmissionMismatch
);

BountyExpired

Code
6003
Message
string
“Bounty deadline has passed”

Description

Reserved for future use. Currently not thrown by any instruction.

Intended Use

This error code exists for potential future enforcement of bounty deadlines. The NullBounty.deadline field is stored on-chain but not currently validated by the program.

Potential Implementation

A future version might add deadline enforcement in submit_to_bounty:
let now = Clock::get()?.unix_timestamp;
require!(bounty.deadline >= now, NullGraphError::BountyExpired);
The frontend currently filters expired bounties based on the deadline field, but the program does not enforce this on-chain.

InvalidRewardAmount

Code
6004
Message
string
“Reward amount must be > 0”

Description

Thrown when attempting to create a bounty with a zero or negative reward amount.

Thrown By

Rationale

A bounty with zero reward provides no incentive and would be pointless. This validation ensures all bounties have economic value.

Code Reference

// create_bounty validation (line 78)
require!(reward_amount > 0, NullGraphError::InvalidRewardAmount);

FeeOverflow

Code
6005
Message
string
“Fee calculation overflow”

Description

Thrown when arithmetic operations during fee calculation result in overflow or underflow.

Thrown By

Security Note

Using checked arithmetic prevents integer overflow attacks. Even though the inputs make overflow practically impossible, defensive programming ensures the program fails safely rather than silently producing incorrect results.

Code Reference

// approve_bounty_submission fee calculation (lines 169-174)
let protocol = &ctx.accounts.protocol_state;
let fee_bps = protocol.fee_basis_points as u64;
let total = bounty.reward_amount;
let fee = total
    .checked_mul(fee_bps)
    .ok_or(NullGraphError::FeeOverflow)?
    .checked_div(10_000)
    .ok_or(NullGraphError::FeeOverflow)?;
let payout = total.checked_sub(fee).ok_or(NullGraphError::FeeOverflow)?;

Error Handling in Client Code

Anchor errors can be caught and decoded in TypeScript:
import { AnchorError } from '@coral-xyz/anchor';

try {
  await program.methods.submitToBounty()
    .accounts({ /* ... */ })
    .rpc();
} catch (err) {
  if (err instanceof AnchorError) {
    switch (err.error.errorCode.code) {
      case 'InvalidBountyStatus':
        console.error('This bounty is not accepting submissions');
        break;
      case 'InvalidRewardAmount':
        console.error('Reward must be greater than 0');
        break;
      default:
        console.error('Unknown error:', err.error.errorMessage);
    }
  }
}

Error Code Summary

CodeNameMessageCurrently Used
6000InvalidBountyStatusBounty is not in the expected statusYes (3 locations)
6001InvalidSubmissionStatusSubmission is not in the expected statusYes (1 location)
6002SubmissionMismatchMatched submission mismatchYes (1 location)
6003BountyExpiredBounty deadline has passedNo (reserved)
6004InvalidRewardAmountReward amount must be > 0Yes (1 location)
6005FeeOverflowFee calculation overflowYes (3 locations)
All Anchor custom errors automatically include the program ID and instruction context in the transaction error logs, making debugging easier.

Build docs developers (and LLMs) love