{"record":{"id":"42121160ef6e3bf9","repo":"nautechsystems/nautilus_trader","slug":"invalid-receipt-log-hash","errorCode":null,"errorMessage":"Invalid receipt log hash","messagePattern":"Invalid receipt log hash","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/rpc/verification.rs","lineNumber":1945,"sourceCode":"}\n\nimpl NormalizedValue for VerifiedReceipt {\n    fn write_normalized(&self, output: &mut Vec<u8>) {\n        output.push(22);\n        self.transaction_hash.write_normalized(output);\n        self.block_hash.write_normalized(output);\n        self.block_number.write_normalized(output);\n        self.gas_used.write_normalized(output);\n        self.effective_gas_price.write_normalized(output);\n        self.transaction_index.write_normalized(output);\n        self.status.write_normalized(output);\n        self.logs.write_normalized(output);\n    }\n}\n\nfn parse_optional_hash(value: Option<&str>) -> anyhow::Result<Option<B256>> {\n    value\n        .map(|value| B256::from_str(value).map_err(|_| anyhow::anyhow!(\"Invalid receipt log hash\")))\n        .transpose()\n}\n\nfn parse_optional_quantity(value: Option<&str>) -> anyhow::Result<Option<u64>> {\n    value\n        .map(|value| {\n            let value = value.strip_prefix(\"0x\").unwrap_or(value);\n            u64::from_str_radix(value, 16)\n                .map_err(|_| anyhow::anyhow!(\"Invalid receipt log quantity\"))\n        })\n        .transpose()\n}\n\n#[cfg(test)]\nmod tests {\n    use alloy::{\n        primitives::{\n            U256, address,","sourceCodeStart":1927,"sourceCodeEnd":1963,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/rpc/verification.rs#L1927-L1963","documentation":"parse_optional_hash converts an optional string field of a transaction receipt log into a B256 (32-byte) hash. If the string is present but not a valid 32-byte hex hash (B256::from_str fails), the error 'Invalid receipt log hash' is returned. This protects downstream code from using malformed log identifiers (e.g. block hash, transaction hash, or log-related hash fields) read from stored or provided receipt data.","triggerScenarios":"Passing a receipt-log row/string whose hash field contains a non-hex string, a hex string shorter or longer than 64 hex chars, or a value with an unexpected 0x-prefix format into the receipt-log parsing path (verification.rs:~1945).","commonSituations":"Corrupted or hand-edited database rows for receipt logs; hashes truncated by column width; values stored without 0x handling that from_str rejects; mixing 32-byte hashes with 20-byte address hex strings.","solutions":["Verify the stored hash value is exactly 64 hex characters (with or without a consistent 0x prefix) and re-encode it correctly","Fix the data source / migration that wrote the malformed hash","Strip a leading 0x and validate with hex::decode before calling the parser","Skip or flag logs with invalid hashes instead of failing the whole receipt parse, if the field is truly optional"],"exampleFix":"// before\nparse_optional_hash(Some(\"0x1234\"))?; // too short -> Invalid receipt log hash\n// after\nlet h = \"0x1234\";\nlet clean = h.trim_start_matches(\"0x\");\nif clean.len() == 64 && clean.chars().all(|c| c.is_ascii_hexdigit()) {\n    parse_optional_hash(h)?;\n}","handlingStrategy":"validation","validationCode":"fn is_valid_b256_hex(s: &str) -> bool {\n    let h = s.trim_start_matches(\"0x\");\n    h.len() == 64 && h.chars().all(|c| c.is_ascii_hexdigit())\n}","typeGuard":"fn as_b256(value: Option<&str>) -> Option<B256> {\n    value.and_then(|v| B256::from_str(v).ok())\n}","tryCatchPattern":"match parse_optional_hash(log_row.hash.as_deref()) {\n    Ok(hash) => use_hash(hash),\n    Err(e) => { warn!(row_id = %log_row.id, \"skipping log with {e}\"); continue; }\n}","preventionTips":["Store hashes as fixed-width 32-byte values or canonical 0x + 64-hex strings","Enforce column widths >= 66 chars for hex hash columns","Validate hash format at ingestion, not at parse time","Do not mix address (20-byte) and hash (32-byte) hex values in the same field"],"tags":["parsing","hex","blockchain"],"backgroundTag":"invalid-argument-format","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}