Why eth_getTransactionReceipt returns null
Last updated:
At a glance
| Property | Value |
|---|---|
| What you get back | "result": null — a successful response, not an error |
| Pending transaction | No receipt yet; eth_getTransactionByHash shows blockNumber null |
| Replaced transaction | Same sender and nonce mined with a different hash — the original never gets a receipt |
| Transaction index depth (Geth default) | --history.transactions = 2,350,000 blocks ("about one year"); 0 keeps the entire chain |
| Old transactions | Read the block's receipts by number when the hash index no longer covers it |
What you see
You send a transaction, get its hash back from eth_sendRawTransaction, and poll eth_getTransactionReceipt. The answer is "result": null — sometimes for a few blocks, sometimes forever. Or you look up an old transaction hash that a block explorer shows as successful, and the receipt is still null.
Why this happens
A receipt only exists once a transaction is included in a block, and the node answers by looking the hash up in its transaction index. While the transaction waits in a mempool there is no receipt yet, and null is the correct answer. If it never gets mined — it was underpriced and evicted, or you (or your wallet) sent a different transaction with the same nonce and a higher fee — the original hash will never have a receipt, because only one transaction per sender and nonce can be included. A hash also belongs to one network: a transaction signed with EIP-155 replay protection includes its chain ID in the signed data and is valid only on that chain, so a receipt lookup on another network returns null. Behind a load balancer, one node may already have imported the block and another may not, so two consecutive calls can disagree for a moment. Finally, the transaction-hash index is itself a node setting: Geth, for example, keeps it for a limited number of recent blocks by default (--history.transactions, 2,350,000 blocks, described as about one year), so an older transaction can return null from eth_getTransactionReceipt and eth_getTransactionByHash on such a node even though its block is still readable.
What to do
- Call eth_getTransactionByHash with the same hash. If it returns the transaction with blockNumber null, it is still pending; if it returns null too, the node does not know the hash at all.
- Check the sender's nonce: if eth_getTransactionCount(sender, "latest") is already above your transaction's nonce and your hash has no receipt, another transaction with that nonce was mined instead — yours was replaced or dropped.
- Confirm eth_chainId on the endpoint you are polling matches the chain the transaction was signed for.
- For an old transaction you know the block of, read eth_getBlockReceipts (or eth_getBlockByNumber) for that block instead of looking it up by hash — block data does not depend on the hash index.
- When polling right after sending, treat a few null answers as normal and keep polling until the transaction is mined, replaced, or your own timeout expires.
When this is not our problem
A null receipt is the Ethereum JSON-RPC answer for "no mined transaction with this hash on this node" on any node, whoever operates it, Triport included. Nothing on the provider side can create a receipt for a transaction that was never mined, or mined on a different chain.
FAQ
- Does a null receipt mean my transaction failed?
- No. A failed (reverted) transaction that was mined has a receipt with status 0x0. Null means the node has no mined transaction for that hash — pending, replaced, dropped, on another chain, or outside the node's transaction index.
- How long can a receipt stay null?
- Until the transaction is mined. If it is replaced or evicted from the mempool it stays null permanently, so check the sender's nonce to know when to stop waiting.