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

  1. Retry against a single consistent RPC endpoint (a dedicated/archive node)
  2. Verify the tx index and block on an explorer to confirm which response was wrong
  3. 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

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


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/8ed2bf61ef98615a. Report an issue: GitHub.