Nonce too low in Ethereum: cause and fix

Rejected before the chain. The node refuses it: no transaction hash, no receipt.

3 min read· Updated

Short answer

Every account has a nonce: a counter of the transactions it has sent, and each value can be used once. "Nonce too low" means you sent a transaction with a nonce the account has already used, so the node refuses it before it reaches a block. Let the client choose the next nonce instead of setting it yourself.

What you will see

Messages printed for it:

  • nonce too low
  • Nonce provided for the transaction is lower than the current nonce of the account.
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 node's check is marked in red with the error nonce too low, and the later steps are dashed: no hash and no receipt.A transaction's path from your code to the node, the mempool, a block and a receipt. The node's check is marked in red with the error nonce too low, and the later steps are dashed: no hash and no receipt.

The node checks every transaction before it puts it in the mempool, and the nonce is one of the checks. When it fails, the node answers at once with an error. There is no transaction hash and nothing reaches a block.

What is a nonce?

A nonce is a counter on the account: the number of transactions it has sent. Only one transaction with a given nonce can run for an account, and that is what stops a signed transaction from being replayed.

So the next nonce is always the number of transactions the account has sent so far. Anything lower was used already, and the node says nonce too low.

An account whose transaction with nonce 0 is mined, so its next free nonce is 1. A second send with nonce 0 is refused with nonce too low, and no hash is named.An account whose transaction with nonce 0 is mined, so its next free nonce is 1. A second send with nonce 0 is refused with nonce too low, and no hash is named.

Why does it happen?

Three causes cover most cases:

  • You set the nonce yourself and reused one. A retry copies the nonce of the first attempt, and the first attempt was mined.
  • Two senders share one account. Two workers, or two agent tool calls, each keep their own count. Sooner or later both send the same number.
  • A retry after a timeout. The first attempt may have reached the chain even though no answer came back. If it was mined, sending the nonce again gives this error. If it is still waiting, you get replacement transaction underpriced instead.

How do I fix it?

  1. Do not pass nonce unless you must. With a local account (a private key), viem asks the node for the account’s transaction count at the pending block and uses that. With an address-only account, such as a wallet or a dev node that signs for you, the wallet or node picks the nonce.
  2. Give the account a nonce manager when sends can overlap. With a local account, viem can keep the counter in your process, so concurrent sends get consecutive nonces:
import { createWalletClient, http, nonceManager } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { mainnet } from 'viem/chains';
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`, { nonceManager });
const client = createWalletClient({ account, chain: mainnet, transport: http() });
// Concurrent sends from this process get consecutive nonces.
await Promise.all([
client.sendTransaction({ to: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', value: 1n }),
client.sendTransaction({ to: '0x70997970C51812dc3A010C7d01b50e0d17dc79C8', value: 2n }),
]);
  1. Before you retry after a timeout, find out what happened. Look up the first attempt by its hash, or read the account’s count again, and only send again if it did not land. A nonce manager covers one process: if several processes send from the same account, give each its own account or send through one place.

What does it look like in a trace?

With hashspan, the refused send is a send span that ends with an error and has no transaction hash, since the node never named one:

send 31337error
error.type
NonceTooLowError
exception.message
Nonce provided for the transaction is lower than the current nonce of the account.
blockchain.tx.hash
not set
The refused second send of the run above. exception.message is on the span's exception event and appears only with errorMessages set to sanitized.

By default a refused send records the error type, and since hashspan 1.1.0 that is the name viem gives the refusal: NonceTooLowError, FeeCapTooLowError, InsufficientFundsError or IntrinsicGasTooLowError. Where viem has no name for it, as with a replacement refusal, it is TransactionRejectedRpcError. Before 1.1.0 every one of them was recorded as TransactionExecutionError, the wrapper viem puts around them. The exception event still carries that wrapper as exception.type. To read the node’s wording as well, turn on errorMessages: 'sanitized' (see the core options). More on how a failed span is marked: span status.

How this page was checked. Reproduced on a local Anvil chain (31337) with viem 2.57.2 and @hashspan/viem 1.1.0 on 2026-10-07: one transaction mined from a fresh account, then the same nonce sent again. The first line is the node's text on Anvil, the second is viem's own message (NonceTooLowError). Other nodes may word the refusal differently.

FAQ

What is a nonce in Ethereum?

A counter on an account: the number of transactions it has sent. Only one transaction with a given nonce can run for an account, which also stops a signed transaction from being replayed (ethereum.org, Accounts).

Is "already known" the same error as "nonce too low"?

No. In geth, already known means the exact same transaction is already in the node's pool, so it is already waiting and sending it again is harmless. viem still files that node message under its NonceTooLowError, which is why you may see the nonce error for it.

Why does an agent hit this more often than a person?

A person sends one transaction at a time from a wallet. An agent can start several tool calls at once, and each one may read or guess the nonce on its own. Two sends from one account then race for the same number.

See it in your own trace

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