{"id":"ERC-6093","name":"Custom Errors for Common Tokens","status":"Final","chain":"both","category":{"id":"comprehension","name":"Comprehension & Display","description":"Making blockchain data readable to humans"},"journeyStages":[{"id":"reading","name":"Reading & Understanding","description":"Interpreting what you're being asked to do"}],"uxImpact":"ERC-6093 defines optional standard custom errors for ERC-20, ERC-721 and ERC-1155 contracts. A compatible error can help explain a failure, but unknown errors and ordinary revert strings remain possible. Treat decoded values as reported context and check the actual token, spender and state before suggesting another approval or transaction.","officialUrl":"https://ercs.ethereum.org/ERCS/erc-6093","lastReviewed":"2026-09-18","lastUpdated":"2026-09-18","kind":"proposal","hasDetailedContent":true,"content":{"id":"ERC-6093","summary":"ERC-6093 defines optional standard custom errors for ERC-20, ERC-721 and ERC-1155 contracts. A compatible error can help explain a failure, but unknown errors and ordinary revert strings remain possible. Treat decoded values as reported context and check the actual token, spender and state before suggesting another approval or transaction.","applicability":{"whenToUse":["A contract emits recognized ERC-6093 custom errors.","Your client can verify relevant state before suggesting a recovery action."],"whenToAvoid":["The error cannot be decoded; use a readable unknown-error fallback.","You would authorize an approval solely from untrusted error arguments."]},"designerTakeaways":["Decode recognized ERC-6093 errors into readable context when the contract returns them.","Show reported balances, allowances, or required values as error context, then verify state before suggesting a remedy.","Share a decoder for recognized signatures and keep an unknown-error fallback for other revert data."],"problemsSolved":[{"problem":"Error messages are unhelpful hex or generic text","oldWay":"\"execution reverted\" or \"0x4e487b71...\"","newWay":"\"ERC20InsufficientBalance(sender, balance, needed)\"","impact":"critical"},{"problem":"Users don't know how to fix failed transactions","oldWay":"\"Transaction failed. Try again?\" (why?)","newWay":"\"Need 10 more USDC. Current balance: 5 USDC\"","impact":"critical"},{"problem":"Each token had different error formats","oldWay":"Parse custom errors for each protocol","newWay":"Recognized ERC-6093 errors use a shared format; non-compliant errors still need a fallback","impact":"high"}],"uxPatterns":[{"name":"Actionable Error Message","description":"Clear error with solution","userFlow":["Transaction reverts with custom error","App decodes error using ERC-6093 ABI","Extracts balance, needed amount","Check relevant on-chain state before presenting the error values as fact","Shows clear comparison","Offers ways to resolve"]},{"name":"Approval Error","description":"Handle insufficient allowance clearly","userFlow":["Swap fails with allowance error","Decode ERC20InsufficientAllowance","Show current vs needed","Independently check the token, spender and allowance, then preview a bounded approval for user confirmation","Retry original action"]}],"uiComponents":[{"name":"ErrorDecoder","description":"Parses ERC-6093 errors into readable format","states":["parsing","decoded","unknown"],"props":["errorData","onDecode"]},{"name":"BalanceErrorCard","description":"Shows balance shortfall with context","states":["insufficient-balance","insufficient-allowance"],"props":["have","need","token","actionSuggestions"]},{"name":"ErrorRecoveryActions","description":"Buttons to resolve the error","states":["ready","resolving","resolved"],"props":["actions[]","onAction"]}],"antiPatterns":[{"pattern":"Showing raw error hex to users","why":"\"0x4e487b71...\" means nothing","instead":"Decode and display human message","severity":"critical"},{"pattern":"Generic \"Transaction failed\" without details","why":"User has no idea what went wrong","instead":"Parse error, show specific reason","severity":"critical"},{"pattern":"No recovery suggestions","why":"User stuck, doesn't know next step","instead":"Offer actions: \"Approve more\" or \"Get tokens\"","severity":"high"}],"keyTakeaways":["ERC-6093 = human-readable token errors","Decode recognized errors when possible and provide a readable fallback with optional technical details","Show what user has vs what they need","Offer clear recovery actions","Common errors: InsufficientBalance, InsufficientAllowance"],"technicalNotes":"ERC-6093 defines custom errors: ERC20InsufficientBalance(sender, balance, needed), ERC20InsufficientAllowance(spender, allowance, needed), ERC721InsufficientApproval(operator, tokenId), etc. Decode using error selector (first 4 bytes) and ABI decode parameters. OpenZeppelin contracts v5+ use these errors. Use of these errors is optional. Contracts can report misleading arguments, so decoded errors must not be the sole evidence for a recovery action. Support classic strings, unknown selectors, empty data and malformed data.","lastUpdated":"2026-09-18","lastReviewed":"2026-09-18","specConstraints":[{"id":"error-argument-semantics","constraint":"Custom token errors must use their named arguments according to the parameter glossary.","appliesTo":"application","normativity":"normative","specQuote":"The names of the error arguments are defined in the [Parameter Glossary](#parameter-glossary) and MUST be used according to those definitions.","specSection":"Specification","specUrl":"https://ercs.ethereum.org/ERCS/erc-6093#specification","designImplication":"Use decoded error arguments to explain the failing balance, allowance, owner, receiver, or token ID. Do not substitute a generic error when the contract provides context."},{"id":"legacy-error-tolerance","constraint":"DApps supporting this error convention should tolerate classic revert strings and different errors from non-compliant tokens.","appliesTo":"application","normativity":"backwards-compatibility","specQuote":"Implementers and DApp developers that implement special support for tokens that are compliant with this EIP, SHOULD tolerate different errors emitted by non-compliant contracts, as well as classic revert strings.","specSection":"Backwards Compatibility","specUrl":"https://ercs.ethereum.org/ERCS/erc-6093#backwards-compatibility","designImplication":"Keep a fallback error state for older tokens and preserve the user’s attempted action when decoding fails."},{"id":"untrusted-error-decoding","constraint":"Error data from untrusted contracts is not a safe instruction for a user interface.","appliesTo":"application","normativity":"security-considerations","specQuote":"malicious contracts could exploit this to encourage untrusted and potentially harmful operations.","specSection":"Security Considerations","specUrl":"https://ercs.ethereum.org/ERCS/erc-6093#security-considerations","designImplication":"Use decoded errors as context, not as authorization to launch a new transaction or approve a spender."}],"sources":[{"label":"ERC-6093 official specification","url":"https://ercs.ethereum.org/ERCS/erc-6093","type":"official-spec"}]},"sources":[{"label":"Official specification","url":"https://ercs.ethereum.org/ERCS/erc-6093","type":"official-spec"},{"label":"Discussion search","url":"https://ethereum-magicians.org/search?q=ERC-6093","type":"discussion"}],"urls":{"canonical":"https://www.eipsfordesigners.com/standards/ERC-6093","markdown":"https://www.eipsfordesigners.com/standards/ERC-6093/content.md","agent":"https://www.eipsfordesigners.com/standards/ERC-6093/agent.md","api":"https://www.eipsfordesigners.com/api/standards/ERC-6093","official":"https://ercs.ethereum.org/ERCS/erc-6093","discussion":"https://ethereum-magicians.org/search?q=ERC-6093"},"freshness":{"lastReviewed":"2026-09-18","lastUpdated":"2026-09-18"}}