{"record":{"id":"2f3e1038b0c16fc8","repo":"linera-io/linera-protocol","slug":"transaction-receipt-not-found-for-tx-hash","errorCode":null,"errorMessage":"transaction receipt not found for {tx_hash}","messagePattern":"transaction receipt not found for (.+?)","errorType":"exception","errorClass":"ProofError","httpStatus":null,"severity":"warning","filePath":"linera-bridge/src/proof/gen.rs","lineNumber":101,"sourceCode":"            .with_context(|| format!(\"invalid RPC URL: {rpc_url}\"))?;\n        let provider = ProviderBuilder::<_, _, Optimism>::default().connect_http(url);\n        Ok(Self {\n            provider: Box::new(provider),\n        })\n    }\n}\n\n#[async_trait]\nimpl DepositProofClient for HttpDepositProofClient {\n    async fn generate_deposit_proof(&self, tx_hash: B256) -> Result<DepositProof, ProofError> {\n        // 1. Get transaction receipt → block hash, tx index\n        let receipt = self\n            .provider\n            .get_transaction_receipt(tx_hash)\n            .await\n            .map_err(|e| ProofError::Transient(e.into()))?\n            .ok_or_else(|| {\n                ProofError::Transient(anyhow::anyhow!(\n                    \"transaction receipt not found for {tx_hash}\"\n                ))\n            })?;\n\n        let block_hash = receipt.inner.block_hash.ok_or_else(|| {\n            ProofError::Transient(anyhow::anyhow!(\"receipt missing block_hash (pending tx?)\"))\n        })?;\n        let tx_index = receipt.inner.transaction_index.ok_or_else(|| {\n            ProofError::Transient(anyhow::anyhow!(\"receipt missing transaction_index\"))\n        })?;\n\n        // 2. Get full block → header RLP\n        let block = self\n            .provider\n            .get_block_by_hash(block_hash)\n            .await\n            .map_err(|e| ProofError::Transient(e.into()))?\n            .ok_or_else(|| {","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-bridge/src/proof/gen.rs#L83-L119","documentation":"In HttpDepositProofClient::generate_deposit_proof, eth_getTransactionReceipt succeeded but returned null. It is wrapped as ProofError::Transient, meaning a retry may succeed — the typical cause is a transaction that is not mined or not yet indexed by the RPC node, or a hash that does not exist on this chain.","triggerScenarios":"Calling generate_deposit_proof(tx_hash) immediately after broadcasting the deposit transaction; --rpc-url pointing at a different chain than the one the tx was sent to; a mistyped or dropped transaction hash; an RPC node whose indexer lags behind block production.","commonSituations":"Public/free RPC endpoints with indexing lag; mixing up networks (Ethereum mainnet RPC with a Base tx hash); tx still in the mempool or dropped due to low gas; automations that generate proofs without waiting for confirmations.","solutions":["Wait until the transaction is mined (1-2 confirmations) and retry","Verify the tx hash exists on that exact network using a block explorer for the same chain","Check --rpc-url matches the chain the deposit was sent to (e.g. Base L2)","If it still fails after finality, the hash is wrong or the tx was dropped — stop retrying"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Preflight: only attempt a proof once the receipt is mined and indexed.\nloop {\n    let r = provider.get_transaction_receipt(tx_hash).await?;\n    if let Some(r) = r.filter(|r| r.inner.block_hash.is_some() && r.inner.transaction_index.is_some()) {\n        break;\n    }\n    tokio::time::sleep(std::time::Duration::from_secs(5)).await;\n}","typeGuard":null,"tryCatchPattern":"match client.generate_deposit_proof(tx_hash).await {\n    Ok(p) => { /* submit ProcessDeposit */ }\n    Err(ProofError::Transient(e)) => { /* schedule retry with backoff */ }\n    Err(ProofError::Permanent(e)) => { /* log, alert, do not retry */ }\n}","preventionTips":["Wait for 1-2 confirmations before generating proofs","Confirm the tx hash exists on the exact chain the RPC serves","Always branch on ProofError::Transient vs Permanent — the enum is the retry contract"],"tags":["evm","rpc","receipt","bridge","transient","proof"],"backgroundTag":"transaction-receipt-not-found","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}