When a quote execution fails, it gets marked as REFUNDED and includes a failReason field that explains why the refund occurred. Understanding these reasons helps you build better error handling and improve user experience.

How Refund Reasons Work

When you check the status of a quote using the Get Execution Status endpoint, refunded quotes include additional context:
{
  "quoteId": "0xfa6094cd...",
  "status": "REFUNDED",
  "user": "0x9b747cC14...",
  "failReason": "SLIPPAGE",
  "originChainOperations": [],
  "destinationChainOperations": []
}

Fail Reason Types

SLIPPAGE

What it means: The market price moved beyond your configured slippage tolerance during execution. Common causes:
  • High market volatility
  • Large order size relative to liquidity
  • Delayed execution
Recommended actions:
  • Retry with a fresh quote for current prices
  • Increase slippage tolerance if appropriate for your use case
  • Execute quotes more quickly after generation
if (status.failReason === 'SLIPPAGE') {
  // Get a fresh quote with current prices
  const newQuote = await getQuote({
    ...originalQuoteParams,
    slippageTolerance: '500' // Increase to 5% if needed
  });
}

INSUFFICIENT_BALANCE

What it means: The user doesn’t have enough tokens to complete the swap. Common causes:
  • User moved tokens after quote generation
  • Concurrent transactions used the same tokens
  • Gas fees reduced available balance
Recommended actions:
  • Check user’s current token balance
  • Verify tokens aren’t locked in other protocols
  • Account for gas fees in balance calculations
if (status.failReason === 'INSUFFICIENT_BALANCE') {
  // Check current balance before retrying
  const balance = await getBalance(userAddress, tokenAddress);
  if (balance.gte(requiredAmount)) {
    // Safe to retry
    await executeNewQuote();
  } else {
    // Inform user about insufficient balance
    showInsufficientBalanceError();
  }
}

TIMEOUT

What it means: Quote execution exceeded the time limit. Common causes:
  • Network congestion causing delays
  • Quote executed too long after generation
  • Multi-chain coordination timeouts
Recommended actions:
  • Generate a new quote and execute promptly
  • Check for network congestion
  • Use shorter expiration times during high volatility

GAS_TOO_LOW

What it means: Insufficient gas was provided for transaction execution. Common causes:
  • Gas limit set too low
  • Complex multi-step operations require more gas
  • Network gas price fluctuations
Recommended actions:
  • Increase gas limit for the transaction
  • Check current network gas prices
  • Use dynamic gas estimation

EXECUTION_FAILED

What it means: On-chain execution failed due to smart contract issues. Common causes:
  • Token has transfer restrictions
  • Smart contract logic prevented execution
  • Invalid transaction data
Recommended actions:
  • Verify token compatibility and restrictions
  • Check if tokens are paused or have special rules
  • Review transaction parameters for correctness

INSUFFICIENT_LIQUIDITY

What it means: Not enough liquidity available to execute the swap at the quoted size. Common causes:
  • Large order relative to available liquidity
  • Liquidity providers removed funds
  • Market conditions changed significantly
Recommended actions:
  • Reduce swap amount
  • Split large swaps into smaller transactions
  • Try alternative routing paths
  • Wait for liquidity conditions to improve
if (status.failReason === 'INSUFFICIENT_LIQUIDITY') {
  // Try with a smaller amount
  const smallerAmount = originalAmount.div(2);
  const newQuote = await getQuote({
    ...originalQuoteParams,
    amount: smallerAmount.toString()
  });
}

REVERTED

What it means: The blockchain transaction was reverted during execution. Common causes:
  • Token contract restrictions
  • Insufficient gas fees
  • Smart contract validation failures
Recommended actions:
  • Check token-specific requirements (fees, whitelist, etc.)
  • Ensure sufficient native tokens for gas
  • Verify contract interaction parameters

PRICE_IMPACT_TOO_HIGH

What it means: The swap would cause excessive price movement in the liquidity pool. Common causes:
  • Large order size relative to pool depth
  • Low liquidity tokens
  • Market maker protections triggered
Recommended actions:
  • Reduce swap amount to minimize impact
  • Split large orders across multiple transactions
  • Consider alternative tokens with better liquidity

INVALID_PATH

What it means: No valid routing path exists between source and destination tokens. Common causes:
  • Tokens lack direct liquidity pairs
  • Routing algorithms couldn’t find efficient path
  • New or illiquid tokens
Recommended actions:
  • Verify both tokens are actively traded
  • Try alternative token pairs
  • Check if tokens are deprecated or delisted

APPROVAL_FAILED

What it means: Token approval process failed or was insufficient. Common causes:
  • User rejected approval transaction
  • Approval amount insufficient for swap + fees
  • Pending approval transaction not confirmed
Recommended actions:
  • Retry token approval process
  • Ensure approval amount covers swap + fees
  • Check for pending approval transactions

NETWORK_CONGESTION

What it means: High network activity caused transaction failures or timeouts. Common causes:
  • Network experiencing high traffic
  • Gas price too low during congestion
  • Mempool delays
Recommended actions:
  • Wait for network conditions to improve
  • Increase gas price for faster processing
  • Monitor network status before retrying

N/A

What it means: No specific fail reason was provided by the system. Common causes:
  • Unexpected system errors
  • Legacy quote formats
  • Unknown failure modes
Recommended actions:
  • Contact support with quote ID for investigation
  • Try generating a fresh quote
  • Check system status for known issues

Best Practices

1. Implement Error Handling

async function handleQuoteStatus(quoteId: string) {
  const status = await getExecutionStatus(quoteId);
  
  if (status.status === 'REFUNDED' && status.failReason) {
    switch (status.failReason) {
      case 'SLIPPAGE':
      case 'TIMEOUT':
        // Retry with fresh quote
        return retryWithNewQuote();
      
      case 'INSUFFICIENT_BALANCE':
        // Check balance and inform user
        return handleInsufficientBalance();
      
      case 'INSUFFICIENT_LIQUIDITY':
        // Suggest smaller amount
        return suggestSmallerAmount();
      
      default:
        // Generic error handling
        return showGenericError(status.failReason);
    }
  }
}

2. User-Friendly Error Messages

Translate technical fail reasons into clear, actionable messages:
const errorMessages = {
  SLIPPAGE: 'Price changed during execution. Click to retry with current prices.',
  INSUFFICIENT_BALANCE: 'You don\'t have enough tokens. Check your balance.',
  TIMEOUT: 'Transaction took too long. Click to try again.',
  INSUFFICIENT_LIQUIDITY: 'Not enough liquidity. Try a smaller amount.',
  // ... more mappings
};

3. Automatic Retry Logic

For certain fail reasons, implement smart retry mechanisms:
const RETRYABLE_REASONS = ['SLIPPAGE', 'TIMEOUT', 'NETWORK_CONGESTION'];

async function executeWithRetry(quoteParams: QuoteParams, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    const quote = await getQuote(quoteParams);
    const result = await executeQuote(quote);
    
    if (result.status === 'COMPLETED') return result;
    
    if (RETRYABLE_REASONS.includes(result.failReason) && attempt < maxRetries) {
      await delay(1000 * attempt); // Exponential backoff
      continue;
    }
    
    return result; // Final attempt or non-retryable error
  }
}

4. Monitor Fail Reason Patterns

Track fail reasons to identify trends and optimize your integration:
// Analytics tracking
function trackFailReason(failReason: string, quoteParams: any) {
  analytics.track('quote_refunded', {
    failReason,
    tokenPair: `${quoteParams.from.asset}/${quoteParams.to.asset}`,
    amount: quoteParams.amount,
    timestamp: new Date().toISOString()
  });
}