linera-io/linera-protocol · error

log data extends past log boundary

Error message

log data extends past log boundary

What it means

The final bounds check on the data field in decode_log: after confirming the data item is a byte string, linera-bridge/src/proof/mod.rs:591 ensures the remaining log payload covers data_header.payload_length before copying log_bytes. Failure means the data length prefix overstates the available bytes — the log is truncated or its inner lengths are inconsistent.

Source

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

    let mut topics_data = &log_data_buf[..topics_header.payload_length];
    log_data_buf = &log_data_buf[topics_header.payload_length..];

    let mut topics = Vec::new();
    while !topics_data.is_empty() {
        let topic = <B256 as alloy_rlp::Decodable>::decode(&mut topics_data)
            .map_err(|e| anyhow!("invalid topic: {e}"))?;
        topics.push(topic);
    }

    // Decode log data (byte string)
    let data_header = alloy_rlp::Header::decode(&mut log_data_buf)
        .map_err(|e| anyhow!("invalid log data RLP: {e}"))?;
    ensure!(
        !data_header.list,
        "log data must be a byte string, not a list"
    );
    ensure!(
        log_data_buf.len() >= data_header.payload_length,
        "log data extends past log boundary"
    );
    let log_bytes = log_data_buf[..data_header.payload_length].to_vec();
    log_data_buf = &log_data_buf[data_header.payload_length..];

    ensure!(
        log_data_buf.is_empty(),
        "trailing data after log fields ({} unexpected bytes)",
        log_data_buf.len()
    );

    Ok(ReceiptLog {
        address,
        topics,
        data: log_bytes,
    })
}

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Re-derive the receipt from a trusted full node and byte-compare to localize the corrupted length field.
  2. Verify the Merkle proof against the header's receipts_root before parsing; a verified proof with failing inner lengths points to your own slicing, an unverified one to bad node data.
  3. Regenerate fixtures via alloy_rlp encoding rather than manual concatenation.
  4. Check transport: HTTP JSON-RPC hex decoding (odd-length hex, 0x-prefix handling) can silently drop bytes.
Defensive patterns

Strategy: try-catch

Try / catch

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

Prevention

When it happens

Trigger: A log whose data-string length prefix exceeds the bytes left inside the declared log payload; truncation of the receipt node after the data header; fixtures appending data bytes without updating the data-item length or the outer log length.

Common situations: Corrupt or partially delivered Merkle proof nodes; test receipts assembled by concatenation where one length field went stale after an edit; provider bugs or proxy middleware mangling responses.

Related errors


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