{"record":{"id":"e79caba745ffdd1d","repo":"AprilNEA/OpenLogi","slug":"sanitized-unifying-receiver-identity-is-not-four-bytes","errorCode":null,"errorMessage":"sanitized Unifying receiver identity is not four bytes","messagePattern":"sanitized Unifying receiver identity is not four bytes","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs","lineNumber":130,"sourceCode":") -> Result<DeviceRoute> {\n    match selected_route {\n        DeviceRoute::Bolt { slot, .. } => {\n            let value = unique_replacement(audit, SanitizedIdentityKind::ReceiverUniqueId)?;\n            if value.len() != 16 || !value.is_ascii() {\n                bail!(\"sanitized Bolt receiver identity is not 16-byte ASCII\");\n            }\n            let receiver_uid = std::str::from_utf8(value)\n                .map_err(|_| anyhow::anyhow!(\"sanitized Bolt receiver identity is not ASCII\"))?\n                .to_string();\n            Ok(DeviceRoute::Bolt {\n                receiver_uid,\n                slot: *slot,\n            })\n        }\n        DeviceRoute::Unifying { slot, .. } => {\n            let value = unique_replacement(audit, SanitizedIdentityKind::ReceiverSerialNumber)?;\n            if value.len() != 4 {\n                bail!(\"sanitized Unifying receiver identity is not four bytes\");\n            }\n            Ok(DeviceRoute::Unifying {\n                receiver_uid: uppercase_hex(value),\n                slot: *slot,\n            })\n        }\n        DeviceRoute::Direct {\n            vendor_id,\n            product_id,\n        } => Ok(DeviceRoute::Direct {\n            vendor_id: *vendor_id,\n            product_id: *product_id,\n        }),\n        DeviceRoute::RawHid { .. } => {\n            bail!(\"raw HID routes are outside HID++ fixture case capture\")\n        }\n    }\n}","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs#L112-L148","documentation":"`derive_replay_route` requires the sanitized ReceiverSerialNumber replacement for a Unifying route to be exactly 4 bytes (Unifying receiver serials are 4-byte values rendered as uppercase hex). Any other length means the sanitized audit data cannot form a valid route and the error aborts.","triggerScenarios":"Replaying a Unifying-routed fixture whose audit ReceiverSerialNumber replacement is missing or not 4 bytes — from hand-edited audits, an incompatible sanitizer output, or a corrupted fixture.","commonSituations":"Manually editing sanitized fixture identities; mixing fixtures across sanitizer/identity-policy versions; a fixture recorded for a Bolt device but replayed through a Unifying route derivation.","solutions":["Re-record the fixture so a correct 4-byte serial replacement is generated","Fix the audit's ReceiverSerialNumber replacement to exactly 4 bytes","Use the openlogi-fixture synthetic identity policy to regenerate identities rather than editing by hand"],"exampleFix":"// before\n\"receiver_serial_number\": \"A1B2C3D4E5\"   // 5 bytes\n// after\n\"receiver_serial_number\": \"A1B2C3D4\"     // 4 bytes","handlingStrategy":"validation","validationCode":"fn valid_unifying_serial(v: &[u8]) -> bool { v.len() == 4 }\nassert!(valid_unifying_serial(&audit.receiver_serial_number), \"sanitized serial must be 4 bytes\");","typeGuard":"fn valid_unifying_serial(v: &[u8]) -> bool {\n    v.len() == 4\n}","tryCatchPattern":null,"preventionTips":["Never hand-edit sanitized identity fields","Regenerate identities via the synthetic identity policy","Don't reuse Bolt fixtures for Unifying route derivation"],"tags":["fixture","sanitization","unifying","identity","validation"],"backgroundTag":"invalid-identifier-format","analyzedSha":"e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8","analyzedAt":"2026-09-13T03:07:16.451Z","contentChangedAt":"2026-09-13T03:07:16.451Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}