{"record":{"id":"727fcf16cf2e38ca","repo":"linera-io/linera-protocol","slug":"invalid-rlp-item-e","errorCode":null,"errorMessage":"invalid RLP item: {e}","messagePattern":"invalid RLP item: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-bridge/src/proof/mod.rs","lineNumber":536,"sourceCode":"\n    for (key, value) in &entries {\n        builder.add_leaf(*key, value);\n    }\n\n    let root = builder.root();\n    let proof_nodes = builder.take_proof_nodes();\n    let proof = proof_nodes\n        .matching_nodes_sorted(&target_key)\n        .into_iter()\n        .map(|(_, bytes)| bytes.to_vec())\n        .collect();\n\n    (root, proof)\n}\n\n/// Skips one RLP item (string or list) by reading its header and advancing past the payload.\nfn skip_rlp_item(data: &mut &[u8]) -> Result<()> {\n    let header = alloy_rlp::Header::decode(data).map_err(|e| anyhow!(\"invalid RLP item: {e}\"))?;\n    ensure!(\n        data.len() >= header.payload_length,\n        \"not enough data to skip RLP item\"\n    );\n    *data = &data[header.payload_length..];\n    Ok(())\n}\n\n/// Decodes a single log entry from RLP.\n///\n/// Enforces the declared payload boundary: after decoding address, topics, and data,\n/// verifies that exactly `payload_length` bytes were consumed.\nfn decode_log(data: &mut &[u8]) -> Result<ReceiptLog> {\n    let log_header =\n        alloy_rlp::Header::decode(data).map_err(|e| anyhow!(\"invalid log RLP: {e}\"))?;\n    ensure!(log_header.list, \"log must be an RLP list\");\n    ensure!(\n        data.len() >= log_header.payload_length,","sourceCodeStart":518,"sourceCodeEnd":554,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-bridge/src/proof/mod.rs#L518-L554","documentation":"skip_rlp_item's Header::decode failed at the current cursor: the next bytes are not a valid RLP item header (string or list). This helper walks block headers (decode_block_header) and receipt prefixes (decode_receipt_logs), so the error means the byte stream diverges from RLP structure at that point — corruption, truncation, or misaligned cursor.","triggerScenarios":"Walking a block header or receipt where a previous field had a wrong payload_length (cursor misalignment), a truncated buffer, or non-RLP data passed as RLP. Note the follow-up ensure 'not enough data to skip RLP item' is the separate out-of-bounds case.","commonSituations":"Truncated or hex-corrupted bytes from storage or fixtures; version drift in header layouts between chains; skipping fields in the wrong order so the cursor lands mid-item.","solutions":["Re-fetch the header/receipt from a trusted source and re-encode rather than patching bytes","Verify the walking order matches the consensus field order for the chain type","Dump the bytes around the failure offset to spot misalignment (previous payload_length vs actual item size)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"fn is_rlp_shaped(b: &[u8]) -> bool {\n    if b.is_empty() { return false; }\n    matches!(b[0], 0x80..=0xff) // any RLP prefix; 0x00..=0x7f is a single byte (valid item)\n        || b[0] < 0x80\n}","typeGuard":null,"tryCatchPattern":"match decode_receipt_logs(&receipt_rlp) {\n    Err(e) if e.to_string().contains(\"invalid RLP item\") => {\n        // cursor misalignment or corruption: re-fetch the source data\n    }\n    other => other?,\n}","preventionTips":["Re-fetch and re-encode headers/receipts rather than repairing bytes","Verify field walking order matches the consensus layout for the chain type","Log the failure offset to detect payload_length misalignment from upstream fields"],"tags":["rlp","decoding","header","receipt","bridge"],"backgroundTag":"rlp-decode-failed","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}