ERC-4337 Error AA10: Sender Already Constructed UserOp Fix
ERC-4337 error AA10 "sender already constructed" is thrown by the EntryPoint contract when a UserOperation contains a non-empty initCode field for an account address that has already been deployed on-chain. Counterfactual smart accounts only use initCode on their initial creation transaction. If your frontend or client SDK fails to clear initCode on subsequent operations, EntryPoint aborts validation immediately to prevent factory re-entrancy. Set initCode to "0x" to resolve.
# Root Cause & Technical Architecture
Under the ERC-4337 specification (both v0.6 and v0.7 EntryPoint architectures), `initCode` specifies the factory address and initialization calldata used to deploy a counterfactual smart contract wallet. During the validation phase, EntryPoint checks if `sender.code.length > 0`. If code is already present at the sender address and `initCode.length > 0`, the EntryPoint triggers `revert("AA10 sender already constructed")` to prevent execution replay and unintended factory re-initialization.
# 4-Step Actionable Diagnostic Protocol
Step-by-Step ResolutionCheck On-Chain Account Code Length Before Construction
Query the target sender address using eth_getCode. If the returned bytecode is not "0x", the account is already deployed and initCode must be cleared.
Configure Client SDK to Clear InitCode Dynamically
In Biconomy, ZeroDev, or Permissionless.js, ensure your wallet client checks account deployment status so subsequent userOps set initCode to "0x".
Reset Local Account Deployment Cache in Bundler Client
If the account was deployed in a recent block, stale RPC or bundler cache can report it as undeployed. Force an RPC cache refresh on your node.
Verify Factory Deterministic Create2 Address
Confirm the calculated sender address matches the exact CREATE2 salt and initialization parameters used by your account factory contract.
# Diagnostic Verification Code / Command
typescript// Viem / Permissionless.js: Check deployment status
import { createPublicClient, http } from 'viem';
import { mainnet } from 'viem/chains';
const client = createPublicClient({ chain: mainnet, transport: http() });
async function prepareUserOp(senderAddress: `0x${string}`, initCode: `0x${string}`) {
const code = await client.getBytecode({ address: senderAddress });
const isDeployed = code && code !== '0x';
// If already deployed, initCode MUST be empty ("0x") to avoid AA10 revert
const finalInitCode = isDeployed ? '0x' : initCode;
return { sender: senderAddress, initCode: finalInitCode };
} 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 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.
ERC-4337 Error AA25: Invalid Account Nonce 2D Sequence Fix
Fix ERC-4337 error AA25 invalid account nonce. Resolve 2D nonce key and sequence collisions in EntryPoint, parallel bundler queues, and sync lags.
# Frequently Asked Questions
FAQ SchemaWhat is the purpose of initCode in ERC-4337?
initCode allows smart accounts to be deployed counterfactually on their very first user transaction, eliminating the need for a separate setup transaction.
Why does EntryPoint reject initCode if the wallet is already deployed?
Allowing initCode on an already-deployed wallet could allow attackers to call malicious factory code or trigger unexpected state overwrites during validation.
Does AA10 cause users to lose gas fees?
When rejected during bundler local simulation, no gas is spent. If included on-chain by a faulty bundler, the bundler absorbs the verification penalty.