Skip to main content
Comprehensive reference for all error codes returned by the DLMM SDK, including causes, context, and recommended resolution strategies.

POOL_NOT_FOUND

Code: POOL_NOT_FOUND
HTTP Status: 404
Category: Pool Errors
Description: The specified pool address does not exist or is not initialized. Common Causes:
  • Invalid pool address provided
  • Pool has not been created yet
  • Pool has been closed or migrated
  • Wrong network (devnet vs mainnet)
Context Fields:
{
  poolAddress: string;
  network: string;
  timestamp: number;
}
Resolution:
try {
  const poolData = await composer.composePoolData(poolAddress);
} catch (error) {
  if (error.code === 'POOL_NOT_FOUND') {
    console.log('Pool not found, check address:', error.context.poolAddress);
    // Verify pool address on explorer or try different network
  }
}

INVALID_POOL_ADDRESS

Code: INVALID_POOL_ADDRESS
HTTP Status: 400
Category: Pool Errors
Description: The provided pool address is not a valid Solana public key. Common Causes:
  • Malformed address string
  • Incorrect address length
  • Invalid base58 characters
  • Null or undefined address
Context Fields:
{
  providedAddress: string;
  expectedFormat: string;
}
Resolution:
import { PublicKey } from '@solana/web3.js';

function validatePoolAddress(address: string): boolean {
  try {
    new PublicKey(address);
    return true;
  } catch {
    return false;
  }
}

POOL_PAUSED

Code: POOL_PAUSED
HTTP Status: 503
Category: Pool Errors
Description: The pool is temporarily paused and not accepting operations. Common Causes:
  • Pool maintenance in progress
  • Security pause activated
  • Administrative intervention
  • Protocol upgrade
Context Fields:
{
  poolAddress: string;
  pausedAt: number;
  estimatedResume?: number;
  reason?: string;
}
Resolution:
// Wait and retry after pause is lifted
await new Promise(resolve => setTimeout(resolve, 60000));
// Or redirect users to alternative pools

RPC and Connection Errors

RPC_CONNECTION_FAILED

Code: RPC_CONNECTION_FAILED
HTTP Status: 503
Category: Network Errors
Description: Failed to establish connection with Solana RPC endpoint. Common Causes:
  • RPC endpoint is down
  • Network connectivity issues
  • Rate limiting by RPC provider
  • Invalid RPC URL
Context Fields:
{
  rpcUrl: string;
  attemptNumber: number;
  lastError: string;
  timestamp: number;
}
Resolution:
// Implement RPC failover
const rpcEndpoints = [
  'https://api.mainnet-beta.solana.com',
  'https://rpc.ankr.com/solana',
  'https://solana-api.projectserum.com'
];

async function withRPCFailover<T>(operation: (rpc: string) => Promise<T>): Promise<T> {
  for (const rpc of rpcEndpoints) {
    try {
      return await operation(rpc);
    } catch (error) {
      if (error.code === 'RPC_CONNECTION_FAILED') {
        continue; // Try next endpoint
      }
      throw error; // Re-throw non-connection errors
    }
  }
  throw new Error('All RPC endpoints failed');
}

RATE_LIMITED

Code: RATE_LIMITED
HTTP Status: 429
Category: Network Errors
Description: Request rate limit exceeded for the RPC endpoint. Common Causes:
  • Too many requests per second
  • Batch operations too large
  • Free tier limits exceeded
  • Shared IP rate limiting
Context Fields:
{
  rpcUrl: string;
  requestsPerSecond: number;
  retryAfter: number;
  limitType: 'requests' | 'bandwidth' | 'compute';
}
Resolution:
// Implement exponential backoff
async function retryWithBackoff<T>(
  operation: () => Promise<T>,
  maxRetries: number = 3
): Promise<T> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      if (error.code === 'RATE_LIMITED' && attempt < maxRetries) {
        const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      throw error;
    }
  }
}

RPC_TIMEOUT

Code: RPC_TIMEOUT
HTTP Status: 408
Category: Network Errors
Description: RPC request exceeded the configured timeout period. Common Causes:
  • Slow network connection
  • RPC endpoint under heavy load
  • Complex queries taking too long
  • Timeout set too low
Context Fields:
{
  rpcUrl: string;
  timeoutMs: number;
  operation: string;
  elapsedMs: number;
}
Resolution:
// Increase timeout for complex operations
const connection = new Connection(rpcUrl, {
  commitment: 'confirmed',
  timeout: 30000 // 30 seconds
});

Data and Calculation Errors

QUOTE_CALCULATION_FAILED

Code: QUOTE_CALCULATION_FAILED
HTTP Status: 422
Category: Calculation Errors
Description: Unable to calculate swap quote due to insufficient liquidity or invalid parameters. Common Causes:
  • Insufficient liquidity for trade size
  • Invalid token amounts
  • Pool state inconsistency
  • Extreme price impact
Context Fields:
{
  fromToken: string;
  toToken: string;
  amount: string;
  availableLiquidity: number;
  requestedAmount: number;
}
Resolution:
try {
  const quote = await pool.getSwapQuote(params);
} catch (error) {
  if (error.code === 'QUOTE_CALCULATION_FAILED') {
    // Reduce trade size and retry
    const reducedAmount = params.amount * 0.5;
    const quote = await pool.getSwapQuote({ ...params, amount: reducedAmount });
  }
}

INSUFFICIENT_LIQUIDITY

Code: INSUFFICIENT_LIQUIDITY
HTTP Status: 422
Category: Calculation Errors
Description: Not enough liquidity in the pool to execute the requested operation. Common Causes:
  • Large trade size relative to pool liquidity
  • Low liquidity pool
  • All liquidity out of range
  • Recent large withdrawals
Context Fields:
{
  poolAddress: string;
  requestedAmount: number;
  availableLiquidity: number;
  utilizationRate: number;
}
Resolution:
// Check liquidity before large operations
const poolData = await composer.composePoolData(poolAddress);
const maxTradeSize = poolData.liquidity.totalValueLocked * 0.05; // 5% max

if (requestedTradeSize > maxTradeSize) {
  // Split into smaller trades or find alternative pools
}

INVALID_BIN_RANGE

Code: INVALID_BIN_RANGE
HTTP Status: 400
Category: Calculation Errors
Description: The specified bin range is invalid or out of bounds. Common Causes:
  • Lower bin ID greater than upper bin ID
  • Bin IDs outside valid range
  • Negative bin step values
  • Bin range too wide
Context Fields:
{
  lowerBinId: number;
  upperBinId: number;
  maxRange: number;
  poolBinStep: number;
}
Resolution:
// Validate bin range before operations
function validateBinRange(lower: number, upper: number): boolean {
  return lower < upper && 
         upper - lower <= 1000 && // Max range
         lower >= 0;
}

Position and User Errors

POSITION_NOT_FOUND

Code: POSITION_NOT_FOUND
HTTP Status: 404
Category: Position Errors
Description: The specified position does not exist or user has no access. Common Causes:
  • Invalid position address
  • Position closed or withdrawn
  • Wrong user account
  • Position on different network
Context Fields:
{
  positionAddress: string;
  userAddress: string;
  poolAddress: string;
}
Resolution:
// Verify position ownership before operations
const positions = await pool.getPositionsByUser(userPublicKey);
const position = positions.find(p => p.address.equals(positionAddress));

if (!position) {
  throw new Error('Position not found or not owned by user');
}

INSUFFICIENT_POSITION_LIQUIDITY

Code: INSUFFICIENT_POSITION_LIQUIDITY
HTTP Status: 422
Category: Position Errors
Description: Position has insufficient liquidity for the requested operation. Common Causes:
  • Attempting to withdraw more than available
  • Position partially closed
  • Fees not claimed affecting calculations
  • Rounding errors in calculations
Context Fields:
{
  positionAddress: string;
  requestedAmount: number;
  availableAmount: number;
  tokenType: 'X' | 'Y';
}
Resolution:
// Check available liquidity before withdrawal
const position = await pool.getPosition(positionAddress);
const availableX = position.liquidityX.toNumber();
const availableY = position.liquidityY.toNumber();

// Withdraw maximum available if requested exceeds
const withdrawAmount = Math.min(requestedAmount, availableX);

POSITION_OUT_OF_RANGE

Code: POSITION_OUT_OF_RANGE
HTTP Status: 409
Category: Position Errors
Description: Position is outside the active trading range and cannot earn fees. Common Causes:
  • Price moved outside position range
  • Position created at wrong range
  • Market volatility
  • Position not rebalanced
Context Fields:
{
  positionAddress: string;
  lowerBinId: number;
  upperBinId: number;
  activeBinId: number;
  distance: number;
}
Resolution:
// Monitor and alert for out-of-range positions
function checkPositionRange(position: UserPosition, activeBinId: number) {
  const isInRange = position.lowerBinId <= activeBinId && 
                   position.upperBinId >= activeBinId;
  
  if (!isInRange) {
    const distance = Math.min(
      Math.abs(position.lowerBinId - activeBinId),
      Math.abs(position.upperBinId - activeBinId)
    );
    
    console.warn(`Position out of range by ${distance} bins`);
  }
  
  return isInRange;
}

Cache and Performance Errors

CACHE_MISS

Code: CACHE_MISS
HTTP Status: 200 (Warning)
Category: Performance Warnings
Description: Requested data not found in cache, fetching from source. Common Causes:
  • Data expired from cache
  • First time request
  • Cache invalidated
  • Cache size limits exceeded
Context Fields:
{
  cacheKey: string;
  requestedAt: number;
  ttl: number;
  hitRate: number;
}
Resolution:
// This is typically handled automatically
// but can be used for performance monitoring
console.log(`Cache miss for ${error.context.cacheKey}, hit rate: ${error.context.hitRate}%`);

BATCH_OPERATION_FAILED

Code: BATCH_OPERATION_FAILED
HTTP Status: 207
Category: Performance Errors
Description: Some operations in a batch request failed while others succeeded. Common Causes:
  • Mixed valid and invalid requests
  • Partial network failures
  • Some pools unavailable
  • Rate limiting during batch
Context Fields:
{
  totalOperations: number;
  successCount: number;
  failureCount: number;
  failures: Array<{
    operation: string;
    error: string;
  }>;
}
Resolution:
// Handle partial batch failures gracefully
try {
  const results = await batchFetchPools(poolAddresses);
} catch (error) {
  if (error.code === 'BATCH_OPERATION_FAILED') {
    const successes = error.context.totalOperations - error.context.failureCount;
    console.log(`Batch completed: ${successes}/${error.context.totalOperations} successful`);
    
    // Process successful results and retry failures
    const failedPools = error.context.failures.map(f => f.operation);
    // Retry failed operations individually
  }
}

Authentication and Permission Errors

UNAUTHORIZED_ACCESS

Code: UNAUTHORIZED_ACCESS
HTTP Status: 401
Category: Auth Errors
Description: User does not have permission to access the requested resource. Common Causes:
  • Wallet not connected
  • Wrong wallet connected
  • Insufficient permissions
  • Session expired
Context Fields:
{
  requiredPermission: string;
  userAddress?: string;
  resource: string;
}
Resolution:
// Ensure wallet is connected before operations
if (!wallet.publicKey) {
  throw new Error('Wallet not connected');
}

// Verify user owns the resource
const owner = await getResourceOwner(resourceAddress);
if (!owner.equals(wallet.publicKey)) {
  throw new Error('User does not own this resource');
}

Error Handling Utilities

Error Classification

Classify errors by category for appropriate handling:
enum ErrorSeverity {
  LOW = 'low',        // Cache miss, warnings
  MEDIUM = 'medium',  // Retryable failures
  HIGH = 'high',      // Data errors, validation
  CRITICAL = 'critical' // System failures, security
}

function classifyError(errorCode: string): ErrorSeverity {
  const severityMap: Record<string, ErrorSeverity> = {
    'CACHE_MISS': ErrorSeverity.LOW,
    'RPC_TIMEOUT': ErrorSeverity.MEDIUM,
    'RATE_LIMITED': ErrorSeverity.MEDIUM,
    'QUOTE_CALCULATION_FAILED': ErrorSeverity.HIGH,
    'POOL_NOT_FOUND': ErrorSeverity.HIGH,
    'RPC_CONNECTION_FAILED': ErrorSeverity.CRITICAL,
    'UNAUTHORIZED_ACCESS': ErrorSeverity.CRITICAL
  };
  
  return severityMap[errorCode] || ErrorSeverity.HIGH;
}

Retry Strategy Selector

Choose appropriate retry strategy based on error type:
function getRetryStrategy(errorCode: string): {
  shouldRetry: boolean;
  maxAttempts: number;
  backoffMs: number;
} {
  const strategies = {
    'RPC_CONNECTION_FAILED': { shouldRetry: true, maxAttempts: 3, backoffMs: 1000 },
    'RPC_TIMEOUT': { shouldRetry: true, maxAttempts: 2, backoffMs: 2000 },
    'RATE_LIMITED': { shouldRetry: true, maxAttempts: 3, backoffMs: 5000 },
    'QUOTE_CALCULATION_FAILED': { shouldRetry: true, maxAttempts: 1, backoffMs: 1000 },
    'POOL_NOT_FOUND': { shouldRetry: false, maxAttempts: 0, backoffMs: 0 },
    'INVALID_POOL_ADDRESS': { shouldRetry: false, maxAttempts: 0, backoffMs: 0 }
  };
  
  return strategies[errorCode] || { shouldRetry: false, maxAttempts: 0, backoffMs: 0 };
}

Error Recovery Patterns

Common recovery patterns for different error types:
async function recoverableOperation<T>(
  operation: () => Promise<T>,
  errorCode: string
): Promise<T> {
  const strategy = getRetryStrategy(errorCode);
  
  if (!strategy.shouldRetry) {
    return operation();
  }
  
  for (let attempt = 1; attempt <= strategy.maxAttempts; attempt++) {
    try {
      return await operation();
    } catch (error) {
      if (attempt === strategy.maxAttempts) {
        throw error;
      }
      
      const delay = strategy.backoffMs * Math.pow(2, attempt - 1);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
  
  throw new Error('Max retry attempts exceeded');
}
This reference provides complete error handling guidance for robust DLMM SDK integration.