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
- Re-derive the receipt from a trusted full node and byte-compare to localize the corrupted length field.
- 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.
- Regenerate fixtures via alloy_rlp encoding rather than manual concatenation.
- 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
- Hex-decode RPC responses with strict validation; silent byte loss produces exactly this class of failure.
- Compare fetched node bytes against a second provider when lengths fail.
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
- log payload extends past available data
- topics payload 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/de147bea4c52fd00.
Report an issue: GitHub.