linera-io/linera-protocol · error · ProofError
tx_index {tx_index} not found in block receipts
Error message
tx_index {tx_index} not found in block receipts What it means
The receipt's transaction_index has no matching entry in the enumerated block receipts. Classified ProofError::Permanent. The two RPC responses (eth_getTransactionReceipt and eth_getBlockReceipts) are mutually inconsistent — different backing nodes behind a load balancer, a reorg between the calls, or an indexing bug on the provider.
Source
Thrown at linera-bridge/src/proof/gen.rs:166
// Convert RPC logs → primitives logs so Encodable2718 is available.
// OpReceiptEnvelope handles both standard types and OP deposit (0x7e).
let canonical_receipts: Vec<(u64, Vec<u8>)> = all_receipts
.into_iter()
.enumerate()
.map(|(idx, r)| {
let consensus_receipt = r.inner.inner.map_logs(|log| log.inner);
let encoded = consensus_receipt.encoded_2718();
(idx as u64, encoded)
})
.collect();
// 5. Build receipt trie and generate proof
let receipt_rlp = canonical_receipts
.iter()
.find(|(idx, _)| *idx == tx_index)
.map(|(_, rlp)| rlp.clone())
.ok_or_else(|| {
ProofError::Permanent(anyhow::anyhow!(
"tx_index {tx_index} not found in block receipts"
))
})?;
let (receipts_root, proof_nodes) =
crate::proof::build_receipt_proof(&canonical_receipts, tx_index);
// Sanity check: computed receipts root matches block header
if receipts_root != block.header.inner.receipts_root {
return Err(ProofError::Permanent(anyhow::anyhow!(
"receipts root mismatch: computed {receipts_root}, \
header says {}. Receipt encoding may be incorrect.",
block.header.inner.receipts_root
)));
}
// Find all DepositInitiated log indices from the canonical receipt
let logs =View on GitHub (pinned to 6c226ddcb3)
Solutions
- Retry against a single consistent RPC endpoint (a dedicated/archive node)
- Verify the tx index and block on an explorer to confirm which response was wrong
- If reproducible on one provider, switch providers or report the inconsistency
Defensive patterns
Strategy: fallback
Try / catch
Err(ProofError::Permanent(e)) if e.to_string().contains("tx_index") => {
// inconsistent RPC data: retry once against a single dedicated endpoint;
// persist the failure with tx_hash and block for diagnostics
} Prevention
- Use one pinned RPC endpoint for the whole proof pipeline instead of load-balanced pools
- Avoid generating proofs during heavy reorg periods
- Log tx_index, block number, and provider identity when this fires to identify the bad endpoint
When it happens
Trigger: Calling generate_deposit_proof while the RPC cluster serves the two answers from nodes at different heights; a reorg replacing the block between the receipt and receipts fetch; a provider whose receipts endpoint is buggy for the block.
Common situations: Load-balanced public RPCs during block production; unstable providers around reorg-heavy periods; automation retrying quickly without pinning to one endpoint.
Related errors
- header RLP hash mismatch: computed {computed_hash}, expected
- block receipts not found for block {block_hash}
- receipts root mismatch: computed {receipts_root}, header say
- transaction receipt not found for {tx_hash}
- receipt missing block_hash (pending tx?)
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/8ed2bf61ef98615a.
Report an issue: GitHub.