Skip to main content
This guide covers common issues you may encounter when using Gelato’s Paymaster and Bundler infrastructure, along with their solutions.

Common Error Codes

ERC-4337 Error Codes

Error CodeDescriptionSolution
AA10Sender already constructedAccount already deployed, use existing address
AA13InitCode failedCheck your account factory and initialization parameters
AA21Signature validation failedVerify signature format and signer key
AA22Timestamp expiredTransaction took too long, retry with fresh signature
AA23Paymaster timestamp expiredPaymaster approval expired, request new approval
AA24Signature errorInvalid signature format or wrong chain ID
AA25Invalid nonceAccount nonce mismatch - may not be deployed
AA31Paymaster deposit too lowCheck your Gas Tank balance
AA33Paymaster validation failedVerify paymaster configuration and Gas Tank balance
AA40Over verification gas limitReduce complexity of your operation
AA41Over execution gas limitSplit into smaller batches

Common Issues

1. UserOperation Execution Reverted

Symptoms:
  • Error message contains “execution reverted”
  • Transaction fails after submission
Causes:
  • Invalid calldata encoding
  • Target contract reverted
  • Insufficient token balance for the operation
Solutions:
// Verify your calldata before sending
import { encodeFunctionData } from "viem";

const callData = encodeFunctionData({
  abi: contractAbi,
  functionName: "transfer",
  args: [recipientAddress, amount],
});

// Test with simulation first
const estimate = await smartWalletClient.estimate({
  payment: sponsored(sponsorApiKey),
  calls: [{ to: contractAddress, data: callData, value: 0n }],
});

2. Paymaster Validation Failed

Symptoms:
  • Error contains “paymaster” or “AA31/AA33”
  • Sponsored transactions fail
Causes:
  • Gas Tank has insufficient balance
  • API key is invalid or doesn’t include the network
  • Paymaster is not configured for the network
Solutions:
  1. Check your Gas Tank balance in the Gelato App
  2. Verify your API key includes the target network
  3. Ensure you’re using the correct API key for sponsored payments
// Verify Gas Tank balance before sending
// Visit: https://app.gelato.cloud/ > Paymaster & Bundler > Gas Tank

3. Insufficient Funds for Gas

Symptoms:
  • Error contains “insufficient funds”
  • Native or ERC-20 payment fails
Causes:
  • User doesn’t have enough native tokens
  • User doesn’t have enough ERC-20 tokens for gas payment
  • Account is not deployed yet
Solutions:
// For native payments - ensure user has ETH
const balance = await publicClient.getBalance({ address: accountAddress });
if (balance < estimatedGas) {
  console.error("Insufficient native token balance");
}

// For ERC-20 payments - ensure user has approved tokens
const tokenBalance = await publicClient.readContract({
  address: tokenAddress,
  abi: erc20Abi,
  functionName: "balanceOf",
  args: [accountAddress],
});

4. Account Not Deployed

Symptoms:
  • Error contains “AA25” or nonce-related errors
  • First transaction fails
Causes:
  • Smart account hasn’t been deployed yet
  • Using wrong account address
Solutions:
// Get the counterfactual address before deployment
const accountAddress = account.address;
console.log("Account address:", accountAddress);

// First transaction will deploy the account automatically
// Ensure you have funds for deployment gas

5. Invalid Signature

Symptoms:
  • Error contains “AA21” or “AA24”
  • Signature validation fails
Causes:
  • Wrong private key
  • Wrong chain ID
  • Signature expired
Solutions:
// Ensure you're using the correct signer
const owner = privateKeyToAccount(process.env.PRIVATE_KEY);
console.log("Signer address:", owner.address);

// Verify chain configuration
console.log("Chain ID:", client.chain.id);

6. Transaction Pending Forever

Symptoms:
  • Transaction submitted but never confirms
  • wait() never resolves
Causes:
  • Network congestion
  • Bundler mempool issues
  • Low gas price
Solutions:
// Add timeout to your wait call
const txHash = await Promise.race([
  response.wait(),
  new Promise((_, reject) =>
    setTimeout(() => reject(new Error("Transaction timeout")), 120000)
  ),
]);

// Or check status manually
const receipt = await bundler.getUserOperationReceipt({
  hash: userOpHash,
});

Debugging Tips

1. Enable Verbose Logging

// Log all transaction details
console.log("Account address:", account.address);
console.log("Chain:", client.chain.name);
console.log("Calls:", JSON.stringify(calls, null, 2));

2. Use Gas Estimation

// Always estimate before executing
const estimate = await smartWalletClient.estimate({
  payment: sponsored(sponsorApiKey),
  calls: [...],
});

console.log(`Estimated gas: ${estimate.fee.gas}`);
console.log(`Estimated fee: ${formatEther(estimate.fee.amount)} ETH`);

3. Check Network Support

Before deploying, verify your network is supported:

4. Verify API Key Configuration

  1. Go to Gelato App
  2. Navigate to Paymaster & Bundler > API Keys
  3. Verify the API key includes your target network
  4. Check the API key type (sponsor vs. non-sponsor)

Getting Help

If you’re still experiencing issues:
  1. Check the Gelato Discord for community support
  2. Review the API Endpoints documentation
  3. Report issues on GitHub

Additional Resources