confirmTransaction hangs or throws BlockheightExceeded — the transaction never landed; add priority fees, not longer timeouts
Symptom: sendRawTransaction returns a signature without error, then confirmation either blocks indefinitely or throws TransactionExpiredBlockheightExceededError / Blockhash not found. Behaviour is intermittent — it works sometimes and fails most of the time.
What all three symptoms mean: the transaction was never included in a block before its blockhash expired. It is a landing problem, not a confirmation problem. That is why the usual guesses do nothing — raising the commitment level, extending the confirmation timeout, re-implementing lastValidBlockHeight polling, or upgrading to a more expensive RPC plan do not change whether a leader chooses to include your transaction.
The dominant cause during congestion is missing priority fees, especially when your instruction touches hot state that many other transactions also write. Fix:
ComputeBudgetProgram.setComputeUnitPrice({ microLamports: N })
ComputeBudgetProgram.setComputeUnitLimit({ units: measuredCUs })Prepend both. Set the price from a live estimate (an RPC provider's priority-fee API, or recent fees for the writable accounts you touch) rather than a constant, and set a realistic CU limit — a tight limit makes your fee-per-CU competitive. They are cheap relative to the cost of a stuck transaction.
Then make the send loop robust: fetch a fresh blockhash immediately before signing, resend the same signed transaction periodically until lastValidBlockHeight passes (resending is idempotent — same signature), use skipPreflight: true only once you have simulated separately, and treat expiry as a retry-with-new-blockhash rather than an error to surface.
Still current in 2026: priority fees remain the mechanism for inclusion ordering, so this diagnosis holds.
Source: adapted from a Stack Exchange answer by McBain (question by mesnia), https://solana.stackexchange.com/questions/9482/solana-sendrawtransaction-confirmtransaction-confirmtransaction-takes-foreve — CC BY-SA 4.0