ERC-4337 Error AA25: Invalid Account Nonce 2D Sequence Fix
ERC-4337 error AA25 "invalid account nonce" occurs when the nonce submitted in a UserOperation does not match the sequential nonce recorded by the EntryPoint contract for that account key. Unlike standard EVM transactions, ERC-4337 utilizes 2D nonces: an upper 192-bit key allows parallel execution channels, while the lower 64 bits must increment sequentially. Query EntryPoint.getNonce(sender, key) to fetch the accurate nonce before submitting, and clear any conflicting mempool transactions.
# Root Cause & Technical Architecture
The ERC-4337 EntryPoint manages nonces as a mapping `mapping(address => mapping(uint192 => uint64)) nonceSequenceNumber`. When a UserOp arrives, EntryPoint extracts `key = nonce >> 64` and `seq = uint64(nonce)`. If `seq` does not match the current stored sequence number for that `(sender, key)` pair, EntryPoint reverts with `AA25 invalid account nonce`. This commonly occurs when client applications broadcast multiple parallel userOps on key 0 without waiting for receipt.
# 4-Step Actionable Diagnostic Protocol
Step-by-Step ResolutionFetch Current 2D Nonce from EntryPoint Contract
Call entryPoint.getNonce(senderAddress, key) via eth_call directly against the RPC to fetch the accurate sequential counter.
Leverage 2D Nonce Keys for Parallel Transactions
To send concurrent UserOperations without waiting for confirmation, allocate distinct 192-bit keys (e.g. key 1 for session keys, key 0 for main).
Clear Stale Bundler Mempool Queues
If a prior UserOp with the same nonce is pending or underpriced in the bundler mempool, replace it by bumping maxPriorityFeePerGas.
Audit Multi-Tab Session Synchronization
If the user has multiple dApp tabs open, synchronize nonce increments across browser tabs using BroadcastChannel or shared state stores.
# Diagnostic Verification Code / Command
typescript// Fetch 2D Nonce from EntryPoint v0.7 Contract
import { createPublicClient, http, parseAbi } from 'viem';
const entryPointAbi = parseAbi([
'function getNonce(address sender, uint192 key) view returns (uint256 nonce)'
]);
async function getAccountNonce(client: any, entryPoint: `0x${string}`, sender: `0x${string}`, key: bigint = 0n) {
const nonce = await client.readContract({
address: entryPoint,
abi: entryPointAbi,
functionName: 'getNonce',
args: [sender, key]
});
// Upper 192 bits: Key | Lower 64 bits: Sequential counter
return nonce;
} Launch ERC-4337 UserOp Decoder
Execute client-side cryptographic simulation and parameter checks safely in your browser via native WebCrypto without sending private keys or mnemonics over the wire.
Read Full Investigation & Recovery Workflow
Explore complete architectural diagrams, edge-case failure trees, and detailed post-mortem analysis in our verified deep guide.
# Related Diagnostic Codes in ERC-4337 & Safe
Related Hex StatusesERC-4337 Error AA10: Sender Already Constructed UserOp Fix
Fix ERC-4337 error AA10 sender already constructed. Resolve non-empty initCode sent for deployed smart accounts, bundler estimation, and counterfactuals.
ERC-4337 Error AA20: Account Not Deployed EntryPoint Revert
Fix ERC-4337 error AA20 account not deployed. Troubleshoot empty initCode for counterfactual smart accounts, factory calldata, and pre-deployment.
ERC-4337 Error AA24: Signature Error UserOp Validation Fix
Fix ERC-4337 error AA24 signature error. Resolve validateUserOp signature mismatch, userOpHash EIP-712 hashing errors, and signature aggregator faults.
# Frequently Asked Questions
FAQ SchemaWhat is a 2D nonce in ERC-4337?
A 2D nonce is a uint256 where the first 192 bits represent a key (independent lane) and the last 64 bits represent a strict sequential counter for that lane.
Can I send parallel transactions with ERC-4337?
Yes! By using different 192-bit keys, you can execute transactions in parallel without sequential blocking, unlike traditional Ethereum accounts.
Why did my transaction get AA25 if I only clicked once?
A retry mechanism in your dApp or bundler may have submitted the same operation twice, with the second attempt colliding with the newly incremented on-chain nonce.