in-solana by Supanode

TransactionExpiredBlockheightExceededError: block height exceeded

The transaction’s blockhash has expired — the current block height has passed the lastValidBlockHeight returned by getLatestBlockhash when the blockhash was fetched. The network will never process this transaction.

Common causes

  1. Transaction took too long to reach a leader. Network congestion, slow RPC forwarding, or insufficient priority fee caused the transaction to sit in queues until its blockhash window closed.
  2. Retry loop ran too long. The application kept resending the same signed transaction past the blockhash validity window (~60-90 seconds).
  3. RPC node latency. The RPC node is far from the current leader or behind the cluster, delaying transaction forwarding.

How to fix

  1. Fetch a fresh blockhash with getLatestBlockhash and note the lastValidBlockHeight.
  2. Rebuild and re-sign the transaction with the new blockhash.
  3. Send the transaction and poll getSignatureStatuses until confirmed or until the current block height (from getBlockHeight) exceeds lastValidBlockHeight.
  4. If block height exceeded without confirmation, repeat from step 1.

How to prevent

  • Add a priority fee to improve the chance of landing during congestion.
  • Use skipPreflight: true and base64 encoding for fastest submission.
  • Send from an RPC node close to validators for lower forwarding latency.
  • Implement a proper retry loop: re-sign with a fresh blockhash once the old one expires, rather than resending the same transaction.
import { createSolanaRpc } from "@solana/kit";

const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");

const { value: { blockhash, lastValidBlockHeight } } =
  await rpc.getLatestBlockhash().send();

// sign transaction with blockhash, then send...

// Poll until confirmed or expired
while (true) {
  const currentHeight = await rpc.getBlockHeight().send();
  if (currentHeight > lastValidBlockHeight) {
    // Blockhash expired — rebuild with a fresh one
    break;
  }
  // check signature status...
}

FAQ

Is the transaction lost? No funds were moved. The transaction was never executed. You can safely retry with a fresh blockhash.

How long is a blockhash valid? Approximately 60-90 seconds, or about 150 blocks. The exact duration depends on block production speed.

Should I use durable nonces instead? Durable nonces do not expire, but they add complexity and a small fee. Use them for transactions that need to survive long delays (offline signing, multisig approvals), not for regular sends.

Error text variants

  • TransactionExpiredBlockheightExceededError
  • block height exceeded
  • Transaction expired

Updated: