Error Handling Guide

This guide covers error handling patterns in the O2 TypeScript SDK.

All API errors extend the base O2Error class:

import { O2Error, InvalidSignature, RateLimitExceeded } from "@o2exchange/sdk";

try {
await client.createOrder("fFUEL/fUSDC", "buy", "0.02", "100");
} catch (error) {
if (error instanceof O2Error) {
console.log(`Code: ${error.code}`);
console.log(`Message: ${error.message}`);
console.log(`Reason: ${error.reason}`);
}
}

The SessionActionsResponse class provides structured success checking:

const response = await client.createOrder("fFUEL/fUSDC", "buy", "0.02", "100");

if (response.success) {
console.log(`TX: ${response.txId}`);
} else if (response.isPreflightError) {
console.log(`Preflight error: ${response.message} (code: ${response.code})`);
} else if (response.isOnChainRevert) {
console.log(`On-chain revert: ${response.reason}`);
}
Code Class Description Recovery
1000 InternalError Unexpected server error Retry with backoff
1001 InvalidRequest Malformed or invalid request Fix request
1002 ParseError Failed to parse request body Fix request format
1003 RateLimitExceeded Too many requests Wait 3-5s (auto-retried)
1004 GeoRestricted Region not allowed Use VPN or different region
Code Class Description Recovery
2000 MarketNotFound Market not found Check market_id
2001 MarketPaused Market is paused Wait for market to resume
2002 MarketAlreadyExists Market already exists Use existing market
Code Class Description Recovery
3000 OrderNotFound Order not found Order may be filled/cancelled
3001 OrderNotActive Order is not active Order already closed
3002 InvalidOrderParams Invalid order parameters Check price/quantity
Code Class Description Recovery
4000 InvalidSignature Signature verification failed Check signing logic
4001 InvalidSession Session invalid or expired Recreate session
4002 AccountNotFound Trading account not found Call setupAccount()
4003 WhitelistNotConfigured Whitelist not configured Whitelist the account
Code Class Description Recovery
5000 TradeNotFound Trade not found Check trade_id
5001 InvalidTradeCount Invalid trade count Adjust count parameter
Code Class Description Recovery
6000 AlreadySubscribed Already subscribed Skip duplicate subscription
6001 TooManySubscriptions Subscription limit reached Unsubscribe from unused streams
6002 SubscriptionError General subscription error Reconnect WebSocket
Code Class Description Recovery
7000 InvalidAmount Invalid amount Check amount value
7001 InvalidTimeRange Invalid time range Fix from/to timestamps
7002 InvalidPagination Invalid pagination params Fix count/offset
7003 NoActionsProvided No actions in request Add at least one action
7004 TooManyActions Too many actions (max 5) Split into multiple batches
Code Class Description Recovery
8000 BlockNotFound Block not found Block may not be indexed yet
8001 EventsNotFound Events not found Events may not be indexed yet

On-chain reverts have no code field — instead, check error.reason for the revert name. These are raised as OnChainRevertError:

import { OnChainRevertError } from "@o2exchange/sdk";

try {
await client.createOrder("fFUEL/fUSDC", "buy", "0.02", "100");
} catch (error) {
if (error instanceof OnChainRevertError) {
console.log(`Revert reason: ${error.reason}`);
// Common reasons:
// - "NotEnoughBalance"
// - "TraderNotWhiteListed"
// - "PricePrecision"
// - "FractionalPrice"
// - "MinOrderNotReached"
}
}

The SDK checks session expiry before submitting actions and raises SessionExpired if the session has expired:

import { SessionExpired } from "@o2exchange/sdk";

try {
await client.createOrder("fFUEL/fUSDC", "buy", "0.02", "100");
} catch (error) {
if (error instanceof SessionExpired) {
await client.createSession(wallet, ["fFUEL/fUSDC"]);
}
}

The SDK automatically retries on RateLimitExceeded errors with exponential backoff. You can configure retry behavior via O2ApiOptions:

import { O2Api, TESTNET } from "@o2exchange/sdk";

const api = new O2Api({
config: TESTNET,
maxRetries: 5,
retryDelayMs: 2000,
timeoutMs: 60_000,
});

The on-chain nonce increments even on reverts. After any error during trading, refresh the nonce to re-sync:

try {
await client.createOrder("fFUEL/fUSDC", "buy", "0.02", "100");
} catch (error) {
await client.refreshNonce();
}
import {
O2Client, O2Error, OnChainRevertError, SessionExpired,
InvalidSession, Network,
} from "@o2exchange/sdk";

const client = new O2Client({ network: Network.TESTNET });
const wallet = O2Client.generateWallet();
await client.setupAccount(wallet);
await client.createSession(wallet, ["fFUEL/fUSDC"]);

async function placeOrder() {
try {
const response = await client.createOrder("fFUEL/fUSDC", "buy", "0.02", "100");
if (response.success) {
console.log(`Success: ${response.txId}`);
}
} catch (error) {
if (error instanceof SessionExpired || error instanceof InvalidSession) {
await client.createSession(wallet, ["fFUEL/fUSDC"]);
return placeOrder();
}
if (error instanceof OnChainRevertError) {
console.log(`On-chain revert: ${error.reason}`);
await client.refreshNonce();
} else if (error instanceof O2Error) {
console.log(`API error ${error.code}: ${error.message}`);
} else {
throw error;
}
}
}