Errors

Every BountyMesh method returns Result<T, Error>. There are 17 typed variants in the Error enum. All are declared at deploy time; new variants would shift discriminants and break SDK consumers with cached IDL.

pub enum Error {
    SelfLoop,
    MarketPaused,
    RewardBelowMinimum,
    InsufficientPayment,
    TitleTooLong,
    DescriptionTooLong,
    AcceptanceTooLong,
    PayloadTooLong,
    IdSpaceExhausted,
    BountyNotFound,
    BountyNotOpen,
    BountyNotClaimed,
    BountyNotSubmitted,
    BountyNotAccepted,
    AlreadyWithdrawn,
    Unauthorized,
    ZeroHashRejected,
}

Variant reference

Anti-cheat

SelfLoopError

msg::source() == exec::program_id(). The program cannot call itself. Returned by every method as the first guard. Defensive; not reachable from any real user flow.

Operator config

MarketPausedError

config.paused == true. Operator-controlled kill switch. Returned by every method as the second guard.

Post-specific

RewardBelowMinimumError

reward < config.min_reward. Mainnet floor is 0.5 VARA (500_000_000_000 atomic). Returned by Post.

InsufficientPaymentError

msg::value() < reward. Caller didn't attach enough VARA. Returned by Post.

TitleTooLongError

title.len() > 200. Returned by Post.

DescriptionTooLongError

description.len() > 2000. Returned by Post.

AcceptanceTooLongError

acceptance.len() > 1000. Returned by Post.

IdSpaceExhaustedError

next_id.checked_add(1) overflowed u64::MAX. Unreachable at any realistic scale. Returned by Post.

Submit-specific

PayloadTooLongError

result_payload.len() > 5000. Returned by Submit.

ZeroHashRejectedError

result_hash == H256::zero(). Catches accidentally-uninitialized hashes. Returned by Submit.

State-transition guards

BountyNotFoundError

id doesn't exist in bounties. Returned by Claim, Submit, Accept, Withdraw.

BountyNotOpenError

Caller tried to claim a bounty whose status is not Open. Returned by Claim.

BountyNotClaimedError

Caller tried to submit against a bounty whose status is not Claimed. Returned by Submit.

BountyNotSubmittedError

Caller tried to accept a bounty whose status is not Submitted. Returned by Accept.

BountyNotAcceptedError

Caller tried to withdraw from a bounty whose status is not Accepted. Returned by Withdraw.

Authorization

UnauthorizedError

Caller's msg::source() doesn't match the expected actor. Returned by:

  • Submit when caller != bounty.worker
  • Accept when caller != bounty.poster
  • Withdraw when caller != bounty.worker

Idempotency

AlreadyWithdrawnError

bounty.withdrawn == true. The worker already pulled the reward. Returned by Withdraw.

Per-method error matrix

ErrorPostClaimSubmitAcceptWithdraw
SelfLoop
MarketPaused
RewardBelowMinimum
InsufficientPayment
TitleTooLong
DescriptionTooLong
AcceptanceTooLong
IdSpaceExhausted
BountyNotFound
BountyNotOpen
BountyNotClaimed
BountyNotSubmitted
BountyNotAccepted
Unauthorized
ZeroHashRejected
PayloadTooLong
AlreadyWithdrawn

SDK error handling pattern

The generated BountyMeshError union is exported from @bountymesh/sdk/errors. Use 'ok' in reply for discrimination:

const result = await sdk.post(signer, params);
 
if ('ok' in result.reply) {
  console.log("bounty id", result.reply.ok);
} else {
  switch (result.reply.err) {
    case 'RewardBelowMinimum':
      console.error("bump reward above 0.5 VARA");
      break;
    case 'InsufficientPayment':
      console.error("attach more value");
      break;
    default:
      console.error("unexpected:", result.reply.err);
  }
}

The error type is generated from the IDL snapshot by scripts/generate-errors.ts. Drift caught by make sdk-check-codegen-drift. Never hand-edit src/errors.generated.ts. See SDK reference.

Refund posture on every Err

All Err branches refund the attached msg::value() via CommandReply::with_value(value). This is the canonical refund-correctness primitive — see Anti-cheat.

msg::send_bytes is NOT used on Err branches. In sails-rs 0.10, outbound messages only flush on successful execution; using msg::send_bytes for Err refunds would silently drop the value into the program balance with no on-chain record. The reply pattern is atomic with the Err return.

Source

Next steps