Execution reverted: what it means and how to fix it

Failed on the chain. It was mined and failed: a hash and a receipt with status reverted.

3 min read· Updated

Short answer

Execution reverted means the contract's code stopped on purpose, with a revert or a failed require, and undid its changes. If the gas is estimated first, you get the error and its reason before anything is sent. If the transaction was sent with a gas limit, it is mined with status reverted and the gas is paid. Read the reason, then fix the input or the state.

What you will see

Messages printed for it:

  • execution reverted
  • execution reverted: Withdrawals are paused
  • Execution reverted with reason: Withdrawals are paused.
On this page

Where does it stop?

A transaction's path from your code to the node, the mempool, a block and a receipt. The block that runs the transaction is marked in red with the error execution reverted: it has a hash and a receipt with status reverted.A transaction's path from your code to the node, the mempool, a block and a receipt. The block that runs the transaction is marked in red with the error execution reverted: it has a hash and a receipt with status reverted.

The contract’s own code decided to stop. That happens when the transaction runs, so a mined transaction has a hash and a receipt with status reverted. You can also meet the same revert earlier, when the gas is estimated.

Two ways to meet the same revert

Two paths for the same revert. With no gas limit given, viem asks the node to estimate first: the estimate reverts with the reason Withdrawals are paused, nothing is sent, and the send span ends with an error. With a gas limit given, the transaction is sent, mined and reverted, and hashspan replays it with eth_call to read the reason; the gas is spent.Two paths for the same revert. With no gas limit given, viem asks the node to estimate first: the estimate reverts with the reason Withdrawals are paused, nothing is sent, and the send span ends with an error. With a gas limit given, the transaction is sent, mined and reverted, and hashspan replays it with eth_call to read the reason; the gas is spent.
  • The estimate fails first. With a local account and no gas limit, viem asks the node to estimate the gas. The revert happens there, and you get the reason before anything is sent: nothing is mined and no gas is spent.
  • The transaction is mined and reverts. With a gas limit you set, or when the state changed after the estimate, the transaction is sent and mined, and the receipt says reverted. The gas is spent.

An address-only account, such as a wallet or a dev node that signs for you, does not go through viem’s estimate: viem hands the transaction to the wallet or node, which decides about gas. In our Anvil run it was accepted and got a hash.

Why does it happen?

  • A failed require or an explicit revert. The contract refuses: it is paused, a limit is exceeded, an allowance or a balance is too low.
  • Wrong arguments or wrong state. The call is valid, but not for the contract’s state now.
  • The state changed since the estimate. Another transaction got there first.

How do I fix it?

  1. Read the reason. viem prints it for an estimate. For a mined transaction, read it from the trace or decode it with the contract’s ABI.
  2. Run the call before you send it. A simulation returns the revert and its reason and costs nothing:
import { createPublicClient, http, parseAbi } from 'viem';
import { mainnet } from 'viem/chains';
declare const account: `0x${string}`;
declare const vault: `0x${string}`;
const publicClient = createPublicClient({ chain: mainnet, transport: http() });
const abi = parseAbi(['function withdraw(uint256 amount)']);
// Run the call against the current state first: a revert comes back with its reason and costs nothing.
const { request } = await publicClient.simulateContract({ account, address: vault, abi, functionName: 'withdraw', args: [1n] });
  1. In an agent, simulate inside the tool and return the reason to the model, so it can change the amount or stop, instead of sending a transaction that is bound to revert.

What does it look like in a trace?

When the estimate fails, the send span ends with an error and no hash, like any refusal. Since hashspan 1.1.0 its error.type is ExecutionRevertedError, the name viem gives a revert. When the transaction is mined, the confirm span carries the reason:

confirm 31337error
blockchain.tx.status
reverted
blockchain.tx.revert.reason
Withdrawals are paused
blockchain.tx.gas.used
21,054
blockchain.tx.fee
42,108,000,000,000
error.type
reverted
The mined revert of the run above. The reason is decoded by replaying the transaction as a call.

The replay uses the state of the previous block, so a transaction that depended on another one in the same block can show no reason or a different one. The long version, with the trace of an agent whose withdrawal reverted, is in your agent’s trace stops at the tool call, and a query for them is in find reverted transactions. A revert without any reason, with gas used equal to the limit, is out of gas.

How this page was checked. Reproduced on a local Anvil chain (31337, Anvil 1.8.3) with viem 2.57.2 and @hashspan/viem 1.1.0 on 2026-10-18: a contract that reverts with Error("Withdrawals are paused"), called from a local (private key) account, once without a gas limit and once with one. The reason text in the lines above is the contract's own; yours will differ.

FAQ

Where is the revert reason?

In the data the contract returns when it reverts. For require(condition, "text") that is an Error(string). A mined transaction does not store it, so a receipt only says reverted. A node returns it for a call or an estimate, and hashspan replays the transaction as a call at the previous block to decode it. A custom error needs the contract's ABI to be decoded.

Does a reverted transaction cost gas?

If it was mined, yes: in our run it used 21,054 gas. If the estimate caught the revert first, nothing was sent, so nothing was spent.

Is it the same as out of gas?

No. Out of gas has no revert reason: the code used the whole limit. A revert has a reason when the contract gave one, and it usually uses part of the limit.

See it in your own trace

Type to search the docs, Learn topics and the blog.