{"record":{"id":"96842d5aff8dff8e","repo":"linera-io/linera-protocol","slug":"log-data-must-be-a-byte-string-not-a-list","errorCode":null,"errorMessage":"log data must be a byte string, not a list","messagePattern":"log data must be a byte string, not a list","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"linera-bridge/src/proof/mod.rs","lineNumber":587,"sourceCode":"    ensure!(\n        log_data_buf.len() >= topics_header.payload_length,\n        \"topics payload extends past log boundary\"\n    );\n\n    let mut topics_data = &log_data_buf[..topics_header.payload_length];\n    log_data_buf = &log_data_buf[topics_header.payload_length..];\n\n    let mut topics = Vec::new();\n    while !topics_data.is_empty() {\n        let topic = <B256 as alloy_rlp::Decodable>::decode(&mut topics_data)\n            .map_err(|e| anyhow!(\"invalid topic: {e}\"))?;\n        topics.push(topic);\n    }\n\n    // Decode log data (byte string)\n    let data_header = alloy_rlp::Header::decode(&mut log_data_buf)\n        .map_err(|e| anyhow!(\"invalid log data RLP: {e}\"))?;\n    ensure!(\n        !data_header.list,\n        \"log data must be a byte string, not a list\"\n    );\n    ensure!(\n        log_data_buf.len() >= data_header.payload_length,\n        \"log data extends past log boundary\"\n    );\n    let log_bytes = log_data_buf[..data_header.payload_length].to_vec();\n    log_data_buf = &log_data_buf[data_header.payload_length..];\n\n    ensure!(\n        log_data_buf.is_empty(),\n        \"trailing data after log fields ({} unexpected bytes)\",\n        log_data_buf.len()\n    );\n\n    Ok(ReceiptLog {\n        address,","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/linera-io/linera-protocol/blob/6c226ddcb332ef55118dc8d0aafbd093d5420899/linera-bridge/src/proof/mod.rs#L569-L605","documentation":"The third field of an Ethereum log is the arbitrary data byte string, and decode_log enforces at linera-bridge/src/proof/mod.rs:587 that its header declares a string (!list). A list header at that position means the bytes do not follow the log schema (address, topics list, data string) — a malformed or non-log item reached the data-field position.","triggerScenarios":"A crafted log whose data field is RLP-encoded as a list (e.g., someone encoded a struct there); a misaligned slice where the previous topics payload was under-consumed so decoding resumes on a nested list; test fixtures encoding data with a helper that wraps content in a list.","commonSituations":"Hand-rolled fixture encoders; receipts from custom chains or tooling that pack structured data as a list in the data slot; off-by-N consumption of the topics list leaving the cursor inside another list.","solutions":["Verify the topics payload was consumed exactly (topics_data emptied by B256 decodes) before reading the data header — a leftover topic shifts the cursor onto the wrong item.","Hex-dump the data-field position: a prefix >= 0xC0 is a list header and proves schema violation; expect 0x80 (empty) or string prefixes.","Re-encode fixtures using Vec<u8>::encode so data is a string item.","If a legitimate emitter encodes list-shaped data, that content is opaque event bytes — it still must be a single RLP string at the receipt layer, so fix the producer."],"exampleFix":"// before (fixture): log data encoded as a list\nvec![vec![1u8, 2, 3]].encode(&mut buf);\n\n// after: log data must be a byte string\nvec![1u8, 2, 3].encode(&mut buf);","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match decode_receipt_logs(receipt_rlp) {\n    Ok(logs) => logs,\n    Err(e) if e.to_string().contains(\"log data must be a byte string\") => {\n        tracing::warn!(\"log data field malformed; rejecting node\");\n        Vec::new()\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["The receipt-layer data field is an opaque byte string: encode opaque payloads with Vec<u8>::encode only.","Ensure topics decode consumed exactly the topics payload before reading the next header."],"tags":["rlp","ethereum","decoding","event-logs","rust","linera-bridge"],"backgroundTag":"rlp-decoding-error","analyzedSha":"6c226ddcb332ef55118dc8d0aafbd093d5420899","analyzedAt":"2026-08-22T22:49:09.787Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}