linera-io/linera-protocol · error

failed to skip receipt field {i}: {e}

Error message

failed to skip receipt field {i}: {e}

What it means

While walking the receipt prefix, skip_rlp_item failed on one of the first three fields (status, cumulative_gas_used, logs_bloom) — the field index i in the message says which. The bytes at that cursor are not a valid RLP item header, so the receipt prefix is malformed or truncated.

Source

Thrown at linera-bridge/src/proof/mod.rs:397

    // EIP-2718: if first byte < 0x80, it's a transaction type prefix
    if data[0] < 0x80 {
        data = &data[1..];
    }

    let list_header =
        alloy_rlp::Header::decode(&mut data).map_err(|e| anyhow!("invalid receipt RLP: {e}"))?;
    ensure!(list_header.list, "receipt must be an RLP list");

    // Limit reads to the receipt's declared payload.
    ensure!(
        data.len() >= list_header.payload_length,
        "receipt payload extends past available data"
    );
    let mut data = &data[..list_header.payload_length];

    // Skip: status (0), cumulative_gas_used (1), logs_bloom (2)
    for i in 0..3 {
        skip_rlp_item(&mut data).map_err(|e| anyhow!("failed to skip receipt field {i}: {e}"))?;
    }

    // Decode the logs list
    let logs_header =
        alloy_rlp::Header::decode(&mut data).map_err(|e| anyhow!("invalid logs list RLP: {e}"))?;
    ensure!(logs_header.list, "logs must be an RLP list");
    ensure!(
        data.len() >= logs_header.payload_length,
        "logs payload extends past receipt boundary"
    );

    let mut logs_data = &data[..logs_header.payload_length];
    let mut logs = Vec::new();
    while !logs_data.is_empty() {
        logs.push(decode_log(&mut logs_data)?);
    }

    Ok(logs)

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Re-derive the receipt bytes from a trusted source (RPC receipt re-encoded via Encodable2718)
  2. Check the field order: status, cumulativeGasUsed, bloom, then logs
  3. Verify the buffer length covers the declared payload (the prior 'extends past available data' check passed, so the corruption is inside the payload)
Defensive patterns

Strategy: try-catch

Try / catch

match decode_receipt_logs(&receipt_rlp) {
    Err(e) if e.to_string().contains("failed to skip receipt field") => {
        // receipt prefix malformed: re-fetch and re-encode the receipt instead of patching bytes
    }
    other => other?,
}

Prevention

When it happens

Trigger: decode_receipt_logs on a receipt whose prefix is truncated (buffer ends mid-field), where a field starts with an invalid length prefix, or where a field that must be a single byte is a long string/list.

Common situations: Truncated receipt bytes from bad hex decoding or storage; hand-crafted receipt fixtures with wrong field ordering; feeding envelope bytes that skip the type byte incorrectly.

Related errors


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