Skip to main content
When a UserOperation fails it surfaces one of two ways: the bundler rejects it during validation (before it touches the chain), or the EntryPoint reverts it during execution (onchain). The error codes and tools below cover both paths.

AA error codes

The ERC-4337 spec reserves the AA prefix for EntryPoint errors. Every string in this table can appear in a UserOperationExecutionError thrown by sendUserOperation or debugUserOperation.

debugUserOperation

StartaleAccountClient exposes debugUserOperation as a drop-in replacement for sendUserOperation. It prints the packed UserOperation, submits it to the bundler, and decodes any AA error code that comes back.
Console output on failure:
Replace sendUserOperation with debugUserOperation during development; swap back before shipping.

Tenderly simulation

debugUserOperation generates a Tenderly simulation URL automatically when these three environment variables are set:
When the variables are present, a URL is logged to the console before the bundler call:
Open the URL in a browser to step through handleOps execution frame by frame, inspect storage reads and writes, and pinpoint the exact revert location, including inside the EntryPoint, your account contract, and your target contract.

Decoding a revert reason manually

If you catch a UserOperationExecutionError, the revert reason is nested inside cause.cause.data:
parseErrorMessage extracts the human-readable string from the failedOp or FailedOpWithRevert revert ABI, the reason JSON field bundlers sometimes attach, and raw hex calldata, whichever format the bundler returns.

Tracing onchain with Blockscout

If the UserOperation lands onchain but the inner call reverts, find it in Blockscout:
  1. Take the UserOperation hash returned by waitForUserOperationReceipt.
  2. Open soneium.blockscout.com (mainnet) or soneium-minato.blockscout.com (testnet).
  3. Paste the hash into the search bar.
  4. Open the User Ops tab and click Decode input data to see the decoded callData and the inner call trace.
The UserOperationEvent log on the same transaction also tells you whether execution succeeded (success: true) or was reverted by the target (success: false with nonzero actualGasCost).

Common patterns

Signature failure (AA23) during development The most frequent cause is a stale nonce or a signer that returns a signature before the UserOp fields are fully populated. Always call account.getNonce() immediately before signing and let the SDK’s sendUserOperation populate gas estimates before the signature step. Gas underestimation Do not hard-code gas limits. The bundler’s eth_estimateUserOperationGas call accounts for the account’s validation logic, the paymaster, and the target call. Overriding callGasLimit or verificationGasLimit below the estimate causes AA41 or AA42 rejections. Paymaster deposit (AA31) The SCS Paymaster dashboard shows your current deposit. If a spike in user activity drains the balance, new UserOperations are rejected at the bundler level before touching the chain. Set up a low-balance alert in the portal.

Next steps

Parallel transactions

Send independent UserOperations on separate nonce lanes to avoid serialization.

Contract interactions

Encode calldata and handle errors in standard single and batched calls.

Sponsored transactions

Configure a paymaster so users never see a gas prompt.

Supported networks

Chain IDs, bundler URLs, and paymaster URLs per network.