RebelfiError Class
All API errors are thrown asRebelfiError instances with structured information:
import { RebelfiError, ErrorCode } from '@rebelfi/sdk';
try {
await client.operations.supply(request);
} catch (error) {
if (error instanceof RebelfiError) {
console.error('Message:', error.message);
console.error('Status:', error.statusCode);
console.error('Code:', error.code);
console.error('Details:', error.details);
}
}
Properties
| Property | Type | Description |
|---|---|---|
message | string | Human-readable error message |
statusCode | number | HTTP status code |
code | ErrorCode | Machine-readable error code |
details | object | Additional error context |
Checking Error Type
Use the.is() method to check for specific errors:
if (error instanceof RebelfiError) {
if (error.is(ErrorCode.INSUFFICIENT_BALANCE)) {
// Show "insufficient funds" message to user
} else if (error.is(ErrorCode.OPERATION_EXPIRED)) {
// Retry with a new operation
}
}
Error Codes
Validation Errors (4xx)
| Code | Description | Recommended Action |
|---|---|---|
INVALID_AMOUNT | Amount is zero, negative, or malformed | Validate amount before calling |
INVALID_ADDRESS | Wallet address format is invalid | Validate address format |
INVALID_TOKEN | Token address not recognized | Use address from strategy |
if (error.is(ErrorCode.INVALID_AMOUNT)) {
// Show validation error to user
showError('Please enter a valid amount');
}
Business Logic Errors (4xx)
| Code | Description | Recommended Action |
|---|---|---|
INSUFFICIENT_BALANCE | Wallet balance too low for operation | Show balance, suggest lower amount |
STRATEGY_NOT_ACTIVE | Strategy is paused or deprecated | Refresh venues, pick another |
ALLOCATION_NOT_FOUND | No position exists at this venue | Check allocations first |
OPERATION_EXPIRED | Unsigned transaction expired | Create new operation |
OPERATION_ALREADY_SUBMITTED | Transaction already submitted | Check operation status |
TOKEN_MISMATCH | Token doesn’t match strategy | Use tokenAddress from strategy |
INVALID_OPERATION_STATUS | Operation in wrong state for action | Check operation status first |
OPERATION_IN_PROGRESS | Another operation is executing for this wallet | Wait for it to complete, or cancel it |
switch (error.code) {
case ErrorCode.INSUFFICIENT_BALANCE:
const balance = error.details?.available;
showError(`Insufficient balance. Available: ${balance}`);
break;
case ErrorCode.STRATEGY_NOT_ACTIVE:
// Refresh and show available strategies
await refreshStrategies();
showError('This strategy is no longer available');
break;
case ErrorCode.OPERATION_EXPIRED:
// Automatically retry
return await retryOperation();
case ErrorCode.OPERATION_IN_PROGRESS:
// Another operation is executing — wait or cancel it
const { operationId, walletId } = error.details as { operationId: number; walletId: number };
showError(`Operation ${operationId} is still executing. Please wait for it to complete.`);
break;
}
Resource Errors (404)
| Code | Description | Recommended Action |
|---|---|---|
VENUE_NOT_FOUND | Venue ID doesn’t exist | Refresh venue list |
STRATEGY_NOT_FOUND | Strategy ID doesn’t exist | Refresh venue list |
OPERATION_NOT_FOUND | Operation ID doesn’t exist | May have been cleaned up |
TRANSACTION_NOT_FOUND | Transaction ID doesn’t exist | Check operation status |
WALLET_NOT_FOUND | Wallet not registered | Register the wallet first via wallets.register() |
ORGANIZATION_NOT_FOUND | API key’s org not found | Check API key |
TOKEN_NOT_FOUND | Token not supported | Check supported tokens |
Simulation Errors (4xx)
| Code | Description | Recommended Action |
|---|---|---|
INSUFFICIENT_GAS | Not enough SOL for transaction fee | Prompt user to add SOL |
SIMULATION_FAILED | Transaction simulation failed | Check error details |
if (error.is(ErrorCode.INSUFFICIENT_GAS)) {
showError('Please add SOL to cover transaction fees');
}
Authentication Errors (401/403)
| Code | Description | Recommended Action |
|---|---|---|
INVALID_API_KEY | API key not recognized | Check API key configuration |
API_KEY_DISABLED | API key has been revoked | Contact support |
Rate Limiting (429)
| Code | Description | Recommended Action |
|---|---|---|
RATE_LIMIT_EXCEEDED | Too many requests | Implement backoff |
if (error.is(ErrorCode.RATE_LIMIT_EXCEEDED)) {
// Exponential backoff
await delay(retryCount * 1000);
return await retry();
}
Network Errors
| Code | Description | Recommended Action |
|---|---|---|
TIMEOUT | Request timed out | Retry with backoff |
NETWORK_ERROR | Network connectivity issue | Check connection, retry |
UNKNOWN_ERROR | Unexpected error | Log and report |
Error Details by Code
Many errors include adetails object with structured context. Here are the fields returned for each error code:
| Error Code | Details Fields | Example |
|---|---|---|
INSUFFICIENT_BALANCE | requested: string, available: string | { "requested": "1000000", "available": "500000" } |
OPERATION_IN_PROGRESS | operationId: number, walletId: number | { "operationId": 123, "walletId": 45 } |
INSUFFICIENT_GAS | walletAddress: string, blockchain: string | { "walletAddress": "So11...abc", "blockchain": "solana" } |
SIMULATION_FAILED | logs?: string[], unitsConsumed?: number | { "logs": ["Program log: Error"], "unitsConsumed": 50000 } |
TOKEN_MISMATCH | expected: string, actual: string | { "expected": "USDC", "actual": "USDT" } |
STRATEGY_NOT_ACTIVE | strategyId: number | { "strategyId": 1 } |
ALLOCATION_NOT_FOUND | strategyId: number, walletAddress: string | { "strategyId": 1, "walletAddress": "So11...abc" } |
Transaction Failure Codes
When a transaction fails, check thefailureCode for details:
const operation = await client.operations.get(operationId);
if (operation.status === 'FAILED') {
const tx = operation.transactions[0];
switch (tx.failureCode) {
case 'REVERTED':
console.error('Contract reverted:', tx.revertReason);
break;
case 'OUT_OF_GAS':
console.error('Transaction ran out of gas');
break;
case 'TIMEOUT':
console.error('Transaction not confirmed in time');
break;
case 'INSUFFICIENT_FUNDS':
console.error('Not enough SOL for gas');
break;
}
}
| Code | Description |
|---|---|
REVERTED | Smart contract execution reverted |
OUT_OF_GAS | Transaction ran out of gas |
TIMEOUT | Not included in block within timeout |
NONCE_TOO_LOW | Nonce already used (duplicate tx) |
INSUFFICIENT_FUNDS | Not enough native token for gas |
REPLACED | Transaction replaced by another |
DROPPED | Dropped from mempool |
UNKNOWN | Unknown failure reason |
Error Handling Patterns
Comprehensive Handler
import { RebelfiError, ErrorCode } from '@rebelfi/sdk';
async function handleSupply(params: SupplyParams) {
try {
const operation = await client.operations.supply(params);
return { success: true, operation };
} catch (error) {
if (!(error instanceof RebelfiError)) {
// Unexpected error
console.error('Unexpected error:', error);
return { success: false, error: 'An unexpected error occurred' };
}
// User-fixable errors
if (error.is(ErrorCode.INSUFFICIENT_BALANCE)) {
return {
success: false,
error: 'Insufficient balance',
userAction: 'deposit_more'
};
}
if (error.is(ErrorCode.INSUFFICIENT_GAS)) {
return {
success: false,
error: 'Need SOL for transaction fee',
userAction: 'add_sol'
};
}
// Retryable errors
if (error.is(ErrorCode.RATE_LIMIT_EXCEEDED) ||
error.is(ErrorCode.TIMEOUT) ||
error.is(ErrorCode.NETWORK_ERROR)) {
return {
success: false,
error: 'Temporary error',
retryable: true
};
}
// Strategy issues
if (error.is(ErrorCode.STRATEGY_NOT_ACTIVE) ||
error.is(ErrorCode.STRATEGY_NOT_FOUND)) {
return {
success: false,
error: 'Strategy unavailable',
userAction: 'select_different_strategy'
};
}
// Auth issues
if (error.is(ErrorCode.INVALID_API_KEY) ||
error.is(ErrorCode.API_KEY_DISABLED)) {
console.error('API key issue:', error.message);
return {
success: false,
error: 'Service configuration error'
};
}
// Unknown API error
return {
success: false,
error: error.message
};
}
}
Retry with Backoff
async function withRetry<T>(
fn: () => Promise<T>,
options: { maxAttempts?: number; baseDelay?: number } = {}
): Promise<T> {
const { maxAttempts = 3, baseDelay = 1000 } = options;
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
if (!(error instanceof RebelfiError)) throw error;
const isRetryable =
error.is(ErrorCode.TIMEOUT) ||
error.is(ErrorCode.NETWORK_ERROR) ||
error.is(ErrorCode.RATE_LIMIT_EXCEEDED);
if (!isRetryable || attempt === maxAttempts) {
throw error;
}
const delay = baseDelay * Math.pow(2, attempt - 1);
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error('Max attempts reached');
}
// Usage
const operation = await withRetry(() =>
client.operations.supply(params)
);
Operation Expiry Handling
async function supplyWithRetry(params: SupplyParams) {
const maxRetries = 2;
for (let i = 0; i < maxRetries; i++) {
try {
const operation = await client.operations.supply(params);
// Check if we have enough time
const expiresAt = new Date(operation.expiresAt);
const timeLeft = expiresAt.getTime() - Date.now();
if (timeLeft < 30000) {
console.warn('Operation expires soon, may need retry');
}
return operation;
} catch (error) {
if (error instanceof RebelfiError &&
error.is(ErrorCode.OPERATION_EXPIRED)) {
console.log('Operation expired, retrying...');
continue;
}
throw error;
}
}
throw new Error('Failed after retries');
}
Next Steps
TypeScript Reference
Complete type definitions
API Reference
REST API documentation