Why a Solana transaction never lands
Last updated:
At a glance
| Property | Value |
|---|---|
| What sendTransaction's signature means | Accepted for forwarding — not processed, not confirmed |
| Blockhash lifetime | 150 blocks; lastValidBlockHeight marks the last valid block height |
| Default preflight | Signature verification, blockhash recency and simulation |
| maxRetries | Overrides the RPC node's default retry logic; 0 lets you rebroadcast yourself |
| Safe to re-sign | Only after the original blockhash has expired |
What you see
sendTransaction answers with a signature and no error. Afterwards getTransaction keeps returning null for that signature, no explorer shows it, and nothing ever reports a failure.
Why this happens
Solana's guide to retrying transactions lists how a transaction gets lost. Before processing, it can be dropped through UDP packet loss, network congestion that overwhelms validators, inconsistencies inside an RPC pool, or by referencing a blockhash that exists only on a lagging minority fork. After processing, it is lost if the cluster switches away from the minority fork it was processed on. Every transaction carries a recent blockhash and expires after 150 blocks; the lastValidBlockHeight returned by getLatestBlockhash marks the last block height at which it can still be included. By default sendTransaction runs preflight checks — signature verification, blockhash recency and a simulation — and then "immediately succeeds, without waiting for any confirmations". Without maxRetries, the node retries sending "until it is finalized or until the blockhash expires"; maxRetries overrides that.
What to do
- Keep preflight on (skipPreflight false) so signature, blockhash and simulation errors come back immediately instead of as a silent drop.
- Record lastValidBlockHeight together with the blockhash you signed with, and poll getBlockHeight against it.
- Rebroadcast the same signed transaction while the blockhash is still valid; if you rebroadcast yourself, set maxRetries to 0 so the node does not also retry.
- Re-sign with a fresh blockhash only after the old one has expired — until then the original transaction can still land.
When this is not our problem
Dropped packets, minority forks and blockhash expiry are properties of how Solana moves transactions to leaders, and they affect every RPC node, whoever operates it, Triport included. Only the client can rebroadcast or re-sign.
FAQ
- Why does my Solana transaction have a signature but never confirm?
- The result is the first signature embedded in the transaction, which exists before sending; it proves nothing about processing. The transaction was dropped before a leader processed it, or processed on a fork that was abandoned. Rebroadcast until the blockhash expires.
- When is it safe to re-sign a Solana transaction?
- Only once the block height has passed the lastValidBlockHeight of the blockhash you originally signed with; before that, the first transaction can still land.