Skip to main content
The Flashnet SDK provides a comprehensive error system with typed error codes, automatic fund recovery, and clear guidance on how to handle each type of failure.

Error Codes

All Flashnet AMM Gateway errors follow the format FSAG-XXXX and are categorized by their numeric range:
RangeCategoryDescription
1000-1999ValidationRequest validation failures
2000-2999SecurityAuthentication and authorization errors
3000-3999InfrastructureExternal service and network issues
4000-4999BusinessAMM logic and pool state errors
5000-5999SystemInternal service errors

Recovery Strategies

Each error has an associated recovery strategy that tells you how to handle fund recovery:
StrategyDescriptionAction Required
clawback_requiredFunds are at risk and must be recoveredClawback will be attempted automatically
clawback_recommendedUncertain state, recovery recommendedClawback will be attempted automatically
auto_refundFunds return automaticallyNo action needed
noneNo funds at riskNo action needed

Automatic Clawback

The SDK automatically attempts to clawback your funds when an operation fails with a clawbackable error. You don’t need to manually handle fund recovery in most cases.
When you execute operations like executeSwap, executeRouteSwap, addLiquidity, or createSingleSidedPool, the SDK:
  1. Sends your funds to the pool
  2. Executes the operation
  3. If the operation fails with a clawbackable error, automatically attempts to recover your funds
  4. Returns a FlashnetError with details about what happened and the recovery status

Example: Handling Auto-Clawback

import { isFlashnetError } from '@flashnet/sdk';

try {
  const swap = await client.executeSwap({
    poolId: "pool-id",
    assetInAddress: "bitcoin-pubkey",
    assetOutAddress: "usdb-pubkey",
    amountIn: "100000000",
    minAmountOut: "99000000",
    maxSlippageBps: 100,
  });
  
  console.log('Swap successful:', swap.amountOut);
} catch (error) {
  if (isFlashnetError(error)) {
    console.log('Error code:', error.errorCode);
    console.log('Category:', error.category);
    console.log('User message:', error.userMessage);
    
    // Check if auto-clawback was attempted
    if (error.wasClawbackAttempted()) {
      const summary = error.clawbackSummary!;
      
      if (error.wereAllTransfersRecovered()) {
        console.log('✅ All funds recovered automatically!');
      } else if (error.werePartialTransfersRecovered()) {
        console.log(`⚠️ Partial recovery: ${summary.successCount}/${summary.totalTransfers}`);
        console.log('Unrecovered transfers:', summary.unrecoveredTransferIds);
      } else {
        console.log('❌ Fund recovery failed');
        console.log('At-risk transfers:', error.transferIds);
      }
    }
    
    // Check specific error types
    if (error.isSlippageError()) {
      console.log('Price moved too much - funds auto-refunded');
    } else if (error.isInsufficientLiquidityError()) {
      console.log('Pool lacks liquidity - funds auto-refunded');
    }
  }
}

Complete Error Code Reference

Validation Errors (1000-1999)

These errors indicate invalid request parameters. Recovery: Clawback Required
CodeHTTPSummaryRetryable
FSAG-1000400Validation failedNo
FSAG-1001400Required field missingNo
FSAG-1002400Invalid field formatNo
FSAG-1003400Value out of rangeNo
FSAG-1004409Duplicate value for unique entityNo

Security Errors (2000-2999)

Authentication and authorization failures. Recovery: Clawback Required (except auth token errors)
CodeHTTPSummaryRetryable
FSAG-2001403Signature verification failedNo
FSAG-2002403Token identity mismatchNo
FSAG-2003401Authorization token missingYes
FSAG-2004401Authorization token invalid/expiredYes
FSAG-2005403Nonce verification failedNo
FSAG-2101400Public key invalidNo

Infrastructure Errors (3000-3999)

External service and network issues. Recovery: Clawback Recommended
CodeHTTPSummaryRetryable
FSAG-3001503Internal server errorYes
FSAG-3002500Internal server errorYes
FSAG-3101500Internal server errorYes
FSAG-3201503Internal server errorYes
FSAG-3201T1503Internal server errorYes
FSAG-3201T2503Internal server errorYes
FSAG-3202503Internal server errorYes
FSAG-3301500Internal server errorYes
FSAG-3302503Internal server errorYes
FSAG-3401500Internal server errorYes
FSAG-3402500Internal server errorYes

Business Errors (4000-4999)

AMM logic and pool state errors. Recovery: Auto Refund (funds return automatically)
CodeHTTPSummaryRetryable
FSAG-4001404Pool not foundNo
FSAG-4002404Host not foundNo
FSAG-4101404Auth session not foundYes
FSAG-4102400Incorrect authentication flowYes
FSAG-4201400Insufficient liquidity/reservesYes
FSAG-4202400Slippage exceeded limitYes
FSAG-4203409Operation not allowed in current phaseYes
FSAG-4204400Insufficient LP token balanceNo
FSAG-4301400Invalid fee configurationNo
FSAG-4401409Spark transfer ID already usedNo

System Errors (5000-5999)

Internal service errors. Recovery: Clawback Required
CodeHTTPSummaryRetryable
FSAG-5001500Failed to generate unique IDYes
FSAG-5002501Feature not implementedNo
FSAG-5003500Internal state inconsistentNo
FSAG-5004500Invalid configuration parameterNo
FSAG-5100500Unexpected panicNo

FlashnetError Properties

The FlashnetError class provides rich error information:
interface FlashnetError extends Error {
  // Core properties
  errorCode: string;           // e.g., "FSAG-4202"
  category: string;            // "Validation" | "Security" | "Infrastructure" | "Business" | "System"
  recovery: string;            // "clawback_required" | "clawback_recommended" | "auto_refund" | "none"
  httpStatus: number;          // HTTP status code
  requestId: string;           // Unique request ID for debugging
  
  // User-facing
  userMessage: string;         // Human-readable explanation
  actionHint: string;          // Suggested action
  isRetryable: boolean;        // Whether retry makes sense
  
  // Clawback info
  transferIds: string[];       // Unrecovered transfer IDs
  lpIdentityPublicKey?: string; // Pool ID for clawback
  clawbackSummary?: {          // Auto-clawback results
    attempted: boolean;
    totalTransfers: number;
    successCount: number;
    failureCount: number;
    recoveredTransferIds: string[];
    unrecoveredTransferIds: string[];
    results: ClawbackAttemptResult[];
  };
}

FlashnetError Methods

// Recovery status
error.isClawbackRequired();        // True if clawback is mandatory
error.isClawbackRecommended();     // True if clawback is advised
error.shouldClawback();            // True if either required or recommended
error.willAutoRefund();            // True if funds return automatically
error.hasTransfersAtRisk();        // True if unrecovered transfers exist

// Clawback status
error.wasClawbackAttempted();      // True if auto-clawback ran
error.wereAllTransfersRecovered(); // True if all funds recovered
error.werePartialTransfersRecovered(); // True if some but not all recovered
error.getRecoveredTransferCount(); // Number of recovered transfers
error.getRecoveredTransferIds();   // IDs of recovered transfers
error.getUnrecoveredTransferIds(); // IDs still at risk

// Error type checks
error.isValidationError();
error.isSecurityError();
error.isInfrastructureError();
error.isBusinessError();
error.isSystemError();

// Specific error checks
error.isSlippageError();           // FSAG-4202
error.isInsufficientLiquidityError(); // FSAG-4201
error.isAuthError();               // FSAG-2003 or FSAG-2004
error.isPoolNotFoundError();       // FSAG-4001
error.isTransferAlreadyUsedError(); // FSAG-4401

// Formatting
error.getUserFriendlyMessage();    // Full user-facing message
error.toLogString();               // Formatted for logging
error.toJSON();                    // Serializable object

Best Practices

1. Always Use Type Guards

import { isFlashnetError, FlashnetError } from '@flashnet/sdk';

try {
  await client.executeSwap({ /* ... */ });
} catch (error) {
  if (isFlashnetError(error)) {
    // Full typed access to error properties
    console.log(error.errorCode, error.userMessage);
  } else {
    // Generic error handling
    console.error('Unknown error:', error);
  }
}

2. Handle Business Errors Gracefully

Business errors (4000-4999) indicate conditions like slippage or insufficient liquidity. These are auto-refunded and often retryable:
if (error.isBusinessError()) {
  if (error.isSlippageError()) {
    // Suggest user increase slippage tolerance
    showMessage('Price moved. Try increasing slippage tolerance.');
  } else if (error.isInsufficientLiquidityError()) {
    // Suggest smaller trade or different pool
    showMessage('Not enough liquidity. Try a smaller amount.');
  }
  
  // Funds are automatically returned
  if (error.willAutoRefund()) {
    showMessage('Your funds will be returned automatically.');
  }
}

3. Log Request IDs for Debugging

catch (error) {
  if (isFlashnetError(error)) {
    console.error(`[${error.requestId}] ${error.toLogString()}`);
    // Report to your error tracking service
    reportError({
      requestId: error.requestId,
      errorCode: error.errorCode,
      ...error.toJSON()
    });
  }
}

4. Implement Retry Logic for Retryable Errors

async function executeWithRetry(fn: () => Promise<any>, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (isFlashnetError(error) && error.isRetryable && attempt < maxRetries) {
        const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
        console.log(`Retrying in ${delay}ms... (attempt ${attempt}/${maxRetries})`);
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      throw error;
    }
  }
}

Next Steps