RPC error -32002: Transaction simulation failed: Blockhash not found

Last updated:

At a glance

Error details
PropertyValue
Code-32002
MessageTransaction simulation failed: Blockhash not found
Categorytransaction

Cause

The blockhash in your transaction is no longer usable by the node processing it, and there are two different reasons for that. It expired. getLatestBlockhash returns lastValidBlockHeight next to the hash — that block height, not an elapsed time, is the deadline the cluster enforces. Once the chain passes it, the transaction can never land. Or the node has not seen it yet. A hash read at processed commitment, or taken from a node further ahead than the one receiving your send, is simply unknown to the receiver until it catches up. The hash is young, but the error is the same.

Solution

  1. Fetch the blockhash with getLatestBlockhash right before signing and keep the lastValidBlockHeight it returns.
  2. Compare it with getBlockHeight while you retry: once the chain passes that height, stop retrying and rebuild the transaction — resubmitting the same bytes can no longer succeed.
  3. Take the blockhash at confirmed (or finalized) commitment rather than processed, so the node receiving the send already knows it.
  4. Use isBlockhashValid to tell the two cases apart before rebuilding: an expired hash needs a new transaction, an unseen one usually just needs a moment.
  5. Track the outcome by signature (getSignatureStatuses, or getTransaction once it lands) instead of resubmitting blindly — a transaction can land even when the send call reported an error.

Expired or unseen? Tell them apart first

The error reads the same for two opposite situations, and the wrong response costs you either a lost transaction or a duplicate one. A blockhash stays valid for 150 blocks, so the question is where the chain is now compared with the lastValidBlockHeight you saved when you fetched it.

Two causes of the same error
ExpiredNot seen yet
getBlockHeight vs lastValidBlockHeightHeight is past itHeight is below it
isBlockhashValidfalse, on any healthy nodefalse now, true shortly
Typical ageOld: you held it too longVery new: often read at processed
Right moveNew blockhash, sign againWait, resend the same bytes
Risk of the wrong moveRetrying can never landRe-signing can land twice

Why seconds are the wrong unit

Guides quote different times for blockhash expiry, because the limit is counted in blocks and slot times change. Compare block heights, which every node reports the same way once it has caught up. A client with a fixed timeout can give up on a transaction that is still valid, and then sign a second one that lands alongside it. Solana's guide says it directly: before re-signing, make sure the original blockhash has expired, because otherwise both transactions can be accepted.

The commitment trap

A blockhash read at processed can belong to a block that the receiving node has not seen, or that a minority fork produced. Solana's docs recommend confirmed for RPC requests, and preflight simulates at preflightCommitment, which defaults to finalized. So a recent hash can fail preflight simply because the finalized bank is older than the hash. Set preflightCommitment to the commitment you fetched the hash with.

const { value } = await rpc("getLatestBlockhash", [{ commitment: "confirmed" }]);
const tx = sign(build(value.blockhash));
await rpc("sendTransaction", [tx, {
  encoding: "base64",
  preflightCommitment: "confirmed",
  maxRetries: 0,
}]);
// keep value.lastValidBlockHeight: it decides when re-signing is safe

When a blockhash is the wrong tool

If a transaction has to wait before it is sent, such as a multisig that collects signatures or an offline signer, a recent blockhash will expire in the meantime however careful you are. Solana's answer for this case is a durable transaction, which uses a nonce account in place of a recent blockhash. It adds an account to manage and an instruction to the transaction, so use it only when the wait is real. For normal sends, fetching the blockhash right before signing is simpler and enough, and it leaves nothing extra for you to fund or track.

Example

{
  "id": 1,
  "error": {
    "code": -32002,
    "message": "Transaction simulation failed: Blockhash not found"
  },
  "jsonrpc": "2.0"
}

FAQ

Why does "Transaction simulation failed: Blockhash not found" happen?
The blockhash in your transaction is no longer usable by the node processing it, and there are two different reasons for that. It expired. getLatestBlockhash returns lastValidBlockHeight next to the hash — that block height, not an elapsed time, is the deadline the cluster enforces. Once the chain passes it, the transaction can never land. Or the node has not seen it yet. A hash read at processed commitment, or taken from a node further ahead than the one receiving your send, is simply unknown to the receiver until it catches up. The hash is young, but the error is the same.
How do I fix "Transaction simulation failed: Blockhash not found"?
Fetch the blockhash with getLatestBlockhash right before signing and keep the lastValidBlockHeight it returns. Compare it with getBlockHeight while you retry: once the chain passes that height, stop retrying and rebuild the transaction — resubmitting the same bytes can no longer succeed. Take the blockhash at confirmed (or finalized) commitment rather than processed, so the node receiving the send already knows it. Use isBlockhashValid to tell the two cases apart before rebuilding: an expired hash needs a new transaction, an unseen one usually just needs a moment. Track the outcome by signature (getSignatureStatuses, or getTransaction once it lands) instead of resubmitting blindly — a transaction can land even when the send call reported an error.
How long is a Solana blockhash valid?
150 blocks. The limit is a block height, not a clock: use lastValidBlockHeight from getLatestBlockhash and compare it with getBlockHeight.
Is it safe to resend after Blockhash not found?
Resending the same signed bytes is safe, since Solana processes a signature at most once. Signing a new transaction is only safe once the old blockhash has expired.
Do I get charged for Blockhash not found?
Not when preflight reports it: the transaction was never forwarded.