Error Codes
Complete reference of Seesaw protocol error codes.
Overview
Error codes are organized by category for easy identification:
Market Errors (0x1001 - 0x100F)
| Code | Name | Description | Resolution |
|---|
0x1001 | MarketNotFound | Market account does not exist | Verify market ID and wait for creation |
0x1002 | MarketExists | Market account already exists | Use existing market |
0x1003 | InvalidState | Operation not valid in current market state | Check market state before operation |
0x1004 | TradingNotStarted | Trading has not begun (start price not snapshotted) | Wait for start price snapshot |
0x1005 | TradingEnded | Trading period has ended | Cannot place new orders |
0x1006 | AlreadySnapshotted | Price snapshot already recorded | No-op, snapshot exists |
0x1007 | AlreadyResolved | Market outcome already determined | No-op, proceed to settlement |
0x1008 | MarketNotResolved | Market not yet resolved | Wait for resolution |
0x1009 | MarketClosed | Market has been closed | Market lifecycle complete |
0x100A | MarketExpired | Market has expired (past expiration window) | Use force close if available |
0x100B | TooEarly | Operation attempted too early | Wait for appropriate time |
0x100C | EpochNotStarted | Epoch has not started yet | Wait for t_start |
0x100D | EpochNotEnded | Epoch has not ended yet | Wait for t_end |
0x100E | NotOwner | Caller is not the owner of the resource | Use correct wallet |
0x100F | PositionsRemaining | Unsettled positions exist; cannot close market | Settle all positions first |
Market Error Examples
// Check if market exists before interacting
try {
const market = await program.account.market.fetch(marketPda);
} catch (e) {
if (e.code === 0x1001) {
console.log('Market not yet created, waiting...');
}
}
// Handle trading state
if (error.code === 0x1005) {
console.log('Trading has ended for this market');
// Redirect to settlement or next market
}
Oracle Errors (0x2001 - 0x2008)
| Code | Name | Description | Resolution |
|---|
0x2001 | InvalidOracleOwner | Oracle account has invalid owner | Verify Pyth program ID |
0x2002 | InvalidOracleFeed | Oracle feed is invalid or malformed | Check feed account data |
0x2003 | OracleMismatch | Pyth feed does not match market configuration | Use correct feed for market |
0x2004 | StaleOracle | Oracle price data is stale | Wait for fresh price update |
0x2005 | InvalidPrice | Oracle reported an invalid price (zero or negative) | Check feed status |
0x2006 | ConfidenceTooWide | Oracle confidence interval exceeds maximum allowed ratio | Wait for more certain price |
0x2007 | OracleNotTrading | Oracle status is not Trading | Wait for feed to resume |
0x2008 | FeedIdMismatch | Pyth feed ID does not match expected feed ID stored in market | Verify feed ID |
Oracle Error Examples
// Handle stale oracle
if (error.code === 0x2004) {
console.log('Oracle price is stale, retrying in 1 second...');
await sleep(1000);
// Retry operation
}
// Handle confidence issues
if (error.code === 0x2006) {
console.log('Price confidence too wide, market may be volatile');
// Consider waiting for better conditions
}
Order Errors (0x3001 - 0x300B)
| Code | Name | Description | Resolution |
|---|
0x3001 | InvalidQuantity | Order quantity is invalid (zero or exceeds maximum) | Use valid quantity (> 0) |
0x3002 | InsufficientCollateral | Insufficient collateral for buy order | Deposit more USDC |
0x3003 | InsufficientShares | Insufficient shares for sell order | Buy shares first or reduce quantity |
0x3004 | OrderbookFull | Order book has reached maximum capacity (64 per side) | Wait for orders to clear |
0x3005 | OrderNotFound | Order not found in the order book | Order may have been filled or cancelled |
0x3006 | WouldCross | PostOnly order would immediately match (cross the spread) | Adjust price or use Limit order |
0x3007 | AlreadySettled | Position has already been settled | No-op, already processed |
0x3008 | NoPosition | User has no position in this market | Trade first to create position |
0x3009 | PriceTooLow | Price is too low (must be at least 1 basis point) | Use price >= 1 bps |
0x300A | PriceTooHigh | Price is too high (must be less than 10000 basis points) | Use price < 10000 bps |
0x300B | CollateralTooLow | Collateral calculation resulted in zero (minimum 1 required) | Increase quantity or price |
Order Error Examples
// Handle insufficient collateral
if (error.code === 0x3002) {
const required = calculateCollateral(price, quantity);
console.log(`Need ${required} USDC to place this order`);
// Prompt user to deposit
}
// Handle PostOnly rejection
if (error.code === 0x3006) {
console.log('Your PostOnly order would match immediately');
// Either adjust price or switch to Limit
}
// Handle order not found
if (error.code === 0x3005) {
console.log('Order not found - may have been filled');
// Refresh order book state
}
Math Errors (0x4001)
| Code | Name | Description | Resolution |
|---|
0x4001 | MathOverflow | Arithmetic overflow or underflow | Use smaller values or check inputs |
Math Error Example
// This typically indicates a bug or extreme values
if (error.code === 0x4001) {
console.error('Math overflow detected - this should not happen');
console.error('Check your input values:', { price, quantity });
// Report as bug if values are reasonable
}
Account Errors (0x5001 - 0x5007)
| Code | Name | Description | Resolution |
|---|
0x5001 | InvalidAccountType | Account discriminator does not match expected type | Use correct account |
0x5002 | InvalidAccountOwner | Account owner is not the expected program | Verify account ownership |
0x5003 | InvalidPDA | PDA derivation does not match expected seeds | Check PDA derivation |
0x5004 | AlreadyInitialized | Account has already been initialized | Use existing account |
0x5005 | InsufficientRentExemption | Account does not have enough lamports for rent exemption | Add more SOL |
0x5006 | InsolvencyDetected | Vault solvency invariant violated | Critical error - contact support |
0x5007 | OrderIdOverflow | Order ID counter overflow | Extremely rare - contact support |
Account Error Examples
// Handle PDA derivation errors
if (error.code === 0x5003) {
// Verify PDA derivation
const [expectedPda] = PublicKey.findProgramAddressSync(
[Buffer.from('seesaw'), Buffer.from('market'), marketIdBuffer],
programId
);
console.log('Expected PDA:', expectedPda.toString());
}
// Handle insolvency (critical)
if (error.code === 0x5006) {
console.error('CRITICAL: Insolvency detected - contact support immediately');
// This indicates a protocol-level issue
}
Position Errors (0x6001 - 0x6002)
| Code | Name | Description | Resolution |
|---|
0x6001 | PositionLimitExceeded | Position size exceeds maximum allowed | Reduce position size |
0x6002 | ProtocolPaused | Protocol is paused | Wait for protocol to resume |
Position Error Examples
// Handle protocol pause
if (error.code === 0x6002) {
console.log('Protocol is currently paused');
// Check announcements for more info
}
Token Architecture Errors (0x7001 - 0x7006)
| Code | Name | Description | Resolution |
|---|
0x7001 | NotImplemented | Instruction not implemented yet | Feature coming soon |
0x7002 | ActiveMarketExists | Active market already exists for this asset | Use existing market |
0x7003 | CannotExpire | Cannot expire market (not past expiration window or already resolved) | Wait for expiration window |
0x7004 | InvalidTokenType | Invalid token type for redemption | Use correct token (YES/NO) |
0x7005 | InvalidRedemption | Cannot redeem tokens that are not winning | Only winning shares pay out |
0x7006 | VaultBalanceMismatch | Vault balance did not change as expected after transfer | Transaction may have failed |
Token Error Examples
// Handle losing position redemption attempt
if (error.code === 0x7005) {
console.log('These shares did not win - payout is 0');
}
// Handle active market check
if (error.code === 0x7002) {
console.log('A market already exists for this epoch');
// Fetch and use existing market
}
Error Handling Best Practices
TypeScript Error Handler
function handleSeesawError(error: any): string {
const code = error.code || error.error?.code;
const errorMessages: Record<number, string> = {
0x1001: 'Market not found - it may not be created yet',
0x1003: 'Invalid market state for this operation',
0x1005: 'Trading has ended for this market',
0x2004: 'Oracle price is stale - try again shortly',
0x3002: 'Insufficient USDC balance for this order',
0x3003: 'Insufficient shares to sell',
0x3006: 'PostOnly order would match - adjust price',
// Add more as needed
};
return errorMessages[code] || `Unknown error: ${code}`;
}
Retry Logic
async function withRetry<T>(
fn: () => Promise<T>,
options: { maxRetries: number; retryableErrors: number[] }
): Promise<T> {
let lastError: any;
for (let i = 0; i < options.maxRetries; i++) {
try {
return await fn();
} catch (e: any) {
lastError = e;
if (!options.retryableErrors.includes(e.code)) {
throw e;
}
await sleep(1000 * Math.pow(2, i));
}
}
throw lastError;
}
// Use with oracle errors
await withRetry(() => snapshotPrice(market), {
maxRetries: 5,
retryableErrors: [0x2004], // StaleOracle
});
Error Code Quick Reference
MARKET (0x10xx) ORACLE (0x20xx) ORDER (0x30xx)
├─ 0x1001 NotFound ├─ 0x2001 InvalidOwner ├─ 0x3001 InvalidQty
├─ 0x1002 Exists ├─ 0x2002 InvalidFeed ├─ 0x3002 NoCollateral
├─ 0x1003 InvalidState ├─ 0x2003 Mismatch ├─ 0x3003 NoShares
├─ 0x1004 NotStarted ├─ 0x2004 Stale ├─ 0x3004 BookFull
├─ 0x1005 Ended ├─ 0x2005 InvalidPrice ├─ 0x3005 NotFound
├─ 0x1006 Snapshotted ├─ 0x2006 WideConf ├─ 0x3006 WouldCross
├─ 0x1007 Resolved ├─ 0x2007 NotTrading ├─ 0x3007 Settled
├─ 0x1008 NotResolved └─ 0x2008 FeedIdMismatch ├─ 0x3008 NoPosition
├─ 0x1009 Closed ├─ 0x3009 PriceLow
├─ 0x100A Expired MATH (0x40xx) ├─ 0x300A PriceHigh
├─ 0x100B TooEarly └─ 0x4001 Overflow └─ 0x300B CollateralLow
├─ 0x100C EpochNotStart
├─ 0x100D EpochNotEnd ACCOUNT (0x50xx) POSITION (0x60xx)
├─ 0x100E NotOwner ├─ 0x5001 InvalidType ├─ 0x6001 LimitExceeded
└─ 0x100F PositionsLeft ├─ 0x5002 InvalidOwner └─ 0x6002 Paused
├─ 0x5003 InvalidPDA
├─ 0x5004 Initialized TOKEN (0x70xx)
├─ 0x5005 NoRent ├─ 0x7001 NotImpl
├─ 0x5006 Insolvent ├─ 0x7002 ActiveExists
└─ 0x5007 IdOverflow ├─ 0x7003 CantExpire
├─ 0x7004 InvalidToken
├─ 0x7005 InvalidRedeem
└─ 0x7006 VaultMismatch
Next Steps
- Review Constants for protocol values
- See Glossary for terminology