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
- 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.
- Retry loop ran too long. The application kept resending the same signed transaction past the blockhash validity window (~60-90 seconds).
- RPC node latency. The RPC node is far from the current leader or behind the cluster, delaying transaction forwarding.
How to fix
- Fetch a fresh blockhash with getLatestBlockhash and note the
lastValidBlockHeight. - Rebuild and re-sign the transaction with the new blockhash.
- Send the transaction and poll getSignatureStatuses until confirmed or until the current block height (from getBlockHeight) exceeds
lastValidBlockHeight. - 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: trueandbase64encoding 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: