linera-io/linera-protocol · error

log payload extends past available data

Error message

log payload extends past available data

What it means

After reading a log's list header, decode_log enforces at linera-bridge/src/proof/mod.rs:553 that the remaining buffer covers header.payload_length before slicing the log's payload boundary. The failure means the log list header declares more payload bytes than exist — truncated log data or a corrupted length prefix. All subsequent field reads are bounded by that declared payload, so this check is the outer safety net for the whole log decode.

Source

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

fn skip_rlp_item(data: &mut &[u8]) -> Result<()> {
    let header = alloy_rlp::Header::decode(data).map_err(|e| anyhow!("invalid RLP item: {e}"))?;
    ensure!(
        data.len() >= header.payload_length,
        "not enough data to skip RLP item"
    );
    *data = &data[header.payload_length..];
    Ok(())
}

/// Decodes a single log entry from RLP.
///
/// Enforces the declared payload boundary: after decoding address, topics, and data,
/// verifies that exactly `payload_length` bytes were consumed.
fn decode_log(data: &mut &[u8]) -> Result<ReceiptLog> {
    let log_header =
        alloy_rlp::Header::decode(data).map_err(|e| anyhow!("invalid log RLP: {e}"))?;
    ensure!(log_header.list, "log must be an RLP list");
    ensure!(
        data.len() >= log_header.payload_length,
        "log payload extends past available data"
    );

    // Limit reads to the declared payload boundary.
    let mut log_data_buf = &data[..log_header.payload_length];
    *data = &data[log_header.payload_length..];

    let address = <Address as alloy_rlp::Decodable>::decode(&mut log_data_buf)
        .map_err(|e| anyhow!("invalid log address: {e}"))?;

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

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Verify the parent logs-list payload length actually covers all entries: logs_data was sliced with logs_header.payload_length — confirm that header matches the real encoded size.
  2. Re-encode the expected log set with alloy_rlp and byte-compare with what you are parsing to find where lengths diverge.
  3. Re-fetch the proof node; a declared-length overflow inside an otherwise valid receipt strongly suggests provider corruption rather than a protocol condition.
  4. If building test receipts, always encode via the library (Encodable) instead of hand-writing length prefixes.

Example fix

// before
ensure!(data.len() >= log_header.payload_length, "log payload extends past available data");

// after
ensure!(
    data.len() >= log_header.payload_length,
    "log payload extends past available data: declared {}, have {} — log RLP truncated",
    log_header.payload_length,
    data.len()
);
Defensive patterns

Strategy: try-catch

Validate before calling

fn log_payload_fits(data: &[u8]) -> Option<bool> {
    let h = alloy_rlp::Header::decode(&mut &data[..]).ok()?;
    Some(h.list && data.len() >= h.payload_length)
}

Try / catch

match decode_receipt_logs(receipt_rlp) {
    Ok(logs) => logs,
    Err(e) if e.to_string().contains("log payload extends past available data") => {
        tracing::warn!(error = %e, "truncated log payload; rejecting proof node");
        Vec::new()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A trie leaf carrying a log whose outer length prefix overstates the content; receipt bytes truncated mid-log (transport or storage cut); a fixture that concatenates logs with a stale total-length header after editing entries.

Common situations: RPC/proof provider returns partial node bytes; receipt RLP rebuilt by hand (build_test_receipt style helpers) after adding a topic without updating the outer payload length; off-by-N slicing when logs_data was carved out of the receipt payload.

Related errors


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