When a smart account transaction gets stuck in the Bundler, it usually hangs at one of three stages—simulation validation failure, insufficient gas estimation, or nonce conflict. The three steps below are far more effective than blindly resending.
1. Step 1: Check the AA Error Codes Returned by the Bundler
After receiving your UserOperation, the Bundler first runs an off-chain simulation. The ERC-4337 specification reserves error codes with the AA prefix for EntryPoint reverts. If calling sendUserOperation throws a UserOperationExecutionError, the error message usually contains an AA-prefixed code.
Step 1: Capture and parse the error from sendUserOperation
What to do: Locate the specific error message returned by the Bundler in your code or wallet logs.
How to do it: Print the full error object inside the
catchblock. If you are using permissionless.js or aa-sdk, temporarily replacesendUserOperationwithdebugUserOperation— it outputs detailed AA error codes and reasons to the console.When you are done: You have obtained a specific AA error code (e.g.,
AA13,AA23,AA31,AA40).
Quick reference for common AA error codes:
| Error Code | Meaning | Possible Cause |
|---|---|---|
| AA13 | InitCode failed | Account factory deployment failed; check initCode or increase verificationGasLimit |
| AA21 | Account did not pre-fund gas | Smart account balance insufficient to pay gas, or Paymaster incorrectly configured |
| AA23 | validateUserOp reverted |
Invalid signature, expired nonce, or an error in the account's validation logic |
| AA25 | Invalid nonce | Nonce does not match the current on-chain state — re-fetch using account.getNonce() |
| AA31 | Paymaster deposit too low | Your Gas Tank or Paymaster account balance is insufficient |
| AA33 | Paymaster validation failed | Paymaster configuration error, or Gas Tank balance insufficient |
| AA40 | verificationGasLimit exceeded |
Gas consumed during the verification phase exceeds the set verificationGasLimit |
| AA41 / AA42 | callGasLimit too low / too high |
Execution-phase gas limits set incorrectly; try letting the Bundler auto-estimate instead of overriding manually |
2. Step 2: Check Gas Estimation Errors (Precheck Failed)
If the Bundler rejects your UserOperation during the off-chain simulation because "gas is too low", you will receive a "precheck failed" type of error.
Step 2: Inspect whether gas limit parameters are too low or too high
What to do: Examine the three fields
callGasLimit,verificationGasLimit, andpreVerificationGas.How to do it:
Case A (error:
callGasLimit is X but must be at least XXXX): Your manually setcallGasLimitis too low. The fix is to remove the manual override and let the Bundler auto-estimate viaeth_estimateUserOperationGas.Case B (error:
verificationGasLimit is X but must be at most XXX): Your verification logic is too complex and exceeds the Bundler's limit. Try simplifying the signature logic, or check with the Paymaster service provider about the upper limit.Case C (error:
maxFeePerGasormaxPriorityFeePerGastoo low): Network fee fluctuations have made your estimate stale. Fetch the latest fee rates usinggetUserOperationGasPrice, or apply a 10%–20% multiplier to the estimated values.
When you are done: You have identified which gas parameter caused the precheck failure and adjusted it accordingly.
3. Step 3: Check Nonce Conflicts (The Most Hidden Trap)
If you send UserOperations with the same nonce to two different Bundlers at the same time, or if your wallet's local nonce count is out of sync with the on-chain state, a nonce collision occurs — after one Bundler's transaction is mined, the other Bundler's transaction containing the same nonce will be reverted, causing that Bundler to waste gas fees and leaving your transaction stuck.
Step 3: Confirm and reset the nonce
What to do: Check whether your account's nonce has been "eaten".
How to do it:
Case A (suspected concurrent submissions): Use a tool or script to query the current
noncevalue of the account on the EntryPoint contract. Make sure your next submission uses the correct next nonce.Case B (receiving AA25 error): Call
account.getNonce()before signing to get the latest value, rather than relying on a cached one.
When you are done: Your submission uses the correct nonce and no longer triggers an AA25 error.
Prerequisite: You are submitting a UserOperation to a Bundler (such as Alchemy, Pimlico, or Gelato's Bundler node) through a wallet or code.
Risk note: If the UserOperation reverts during the on-chain execution phase (e.g., the target contract method does not exist, insufficient balance) but passes the verification phase, the Bundler will still charge gas fees. If the Bundler's transaction is reverted due to a nonce collision, it only loses gas fees and does not deduct from your account, but you will need to resubmit the UserOperation.
After completing the above checks, how do you confirm the issue is resolved?
Find the Bundler's handleOps transaction on a block explorer (e.g., Etherscan) and examine the internal UserOperationEvent log — if the success field is true, your UserOperation executed successfully. If you are using Pimlico's or Alchemy's Bundler, you can also call getUserOperationReceipt to directly query the on-chain execution status of the UserOperationHash.


