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
- 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.
- Re-encode the expected log set with alloy_rlp and byte-compare with what you are parsing to find where lengths diverge.
- Re-fetch the proof node; a declared-length overflow inside an otherwise valid receipt strongly suggests provider corruption rather than a protocol condition.
- 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
- Reject proofs whose declared lengths exceed the delivered bytes; never pad or guess.
- Verify total node length equals header + payload before entering per-field decoding.
- Re-fetch from a different provider when a node fails bounds checks to distinguish corruption from protocol data.
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
- topics payload extends past log boundary
- log data extends past log boundary
- not enough data to skip RLP item
- log must be an RLP list
- topics must be an RLP list
AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22).
Data as JSON: /api/errors/f68cae51e7165e6c.
Report an issue: GitHub.