Transaction

BlockhashNotFound on sendTransaction

Your transaction failed with `BlockhashNotFound`. You used a blockhash the validator that received your submit no longer has in its recent cache — either stale, or you got it from a different node in a load-balanced pool.

Root causes

Ranked by frequency. First cause is the one to check first.

  1. 01You fetched the blockhash minutes before signing. Solana invalidates blockhashes after ~2 minutes (150 slots × 400ms).
  2. 02Your RPC endpoint is a pool, and `getLatestBlockhash` hit one node while `sendTransaction` went to another that's slightly behind in slot height.
  3. 03You used `commitment: 'processed'` when fetching the blockhash. Some validators reject blockhashes that are processed-only because they haven't fully confirmed yet.

Fix steps

  1. 1

    Always fetch a fresh blockhash immediately before signing

    Structure: `const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('confirmed')`, sign, submit. No async work between those three steps.

  2. 2

    Use commitment: confirmed or finalized

    For `getLatestBlockhash`, use `confirmed` at minimum. `processed` blockhashes are too fresh and some validators reject them.

  3. 3

    Route fetch and submit to the same endpoint

    Subglow's `sendTransaction` path has its own quota bucket — use the same `https://rpc.subglow.io` for both fetch and submit to guarantee same-backend routing. On credit-metered providers with multiple backend nodes, this consistency is not guaranteed.

  4. 4

    Include the lastValidBlockHeight

    Pass `lastValidBlockHeight` to `sendTransaction` / `sendAndConfirmTransaction`. The client will stop retrying once the blockhash expires instead of hammering the endpoint pointlessly.

Code example

safe-send.tsts
import { Connection, Transaction } from "@solana/web3.js";

const connection = new Connection("https://rpc.subglow.io/?api-key=YOUR_KEY", "confirmed");

async function sendSafe(tx: Transaction, signers: Keypair[]) {
  const { blockhash, lastValidBlockHeight } =
    await connection.getLatestBlockhash("confirmed");
  tx.recentBlockhash = blockhash;
  tx.lastValidBlockHeight = lastValidBlockHeight;
  tx.feePayer = signers[0].publicKey;
  tx.sign(...signers);
  const sig = await connection.sendRawTransaction(tx.serialize(), {
    skipPreflight: true,
    maxRetries: 0,
  });
  await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, "confirmed");
  return sig;
}

Related errors

Want an endpoint that just works?

Subglow is flat-priced Solana gRPC + JSON-RPC on a single API key. Pre-parsed JSON, dedicated sendTransaction bucket, 99.9% latency SLA on Dedicated. No credit juggling, no surprise bills.