{"record":{"id":"56e44c0dcee17fcc","repo":"AprilNEA/OpenLogi","slug":"sanitized-bolt-receiver-identity-is-not-ascii","errorCode":null,"errorMessage":"sanitized Bolt receiver identity is not ASCII","messagePattern":"sanitized Bolt receiver identity is not ASCII","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs","lineNumber":120,"sourceCode":"            id: cassette.channel.clone(),\n            connection: ChannelConnection::Connected,\n            report_support: cassette.report_support,\n        }],\n    }\n}\n\nfn derive_replay_route(\n    selected_route: &DeviceRoute,\n    audit: &HidCassetteAudit,\n) -> 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,","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs#L102-L138","documentation":"`derive_replay_route` rebuilds a `DeviceRoute::Bolt` for replay from the cassette's audit record of sanitized identities. The sanitized receiver unique-id replacement must be exactly 16 bytes of ASCII (it becomes the receiver UID string); if it isn't, replay cannot reconstruct a valid route and this error is thrown (distinct sibling messages cover the non-16-byte vs non-ASCII cases).","triggerScenarios":"Replaying or validating a cassette whose audit lists a `ReceiverUniqueId` sanitized replacement that is not 16-byte ASCII — e.g. a cassette produced by an older sanitizer, hand-edited audit, or corrupted synthetic value.","commonSituations":"Replaying cassettes generated before the sanitizer enforced the 16-byte ASCII format, fixtures edited by hand for privacy review, or an audit file truncated/corrupted in transit.","solutions":["Re-record the fixture so the sanitizer produces a correct 16-byte ASCII receiver unique-id","Fix the audit `replacements` entry to hold a 16-byte ASCII synthetic value (and keep it consistent with every place it appears)","Check cassette/schema version compatibility between the producing and replaying tool versions","Validate the cassette with the fixture crate's privacy/relationship verification before replay"],"exampleFix":"// before (hand-edited audit)\n[[replacements]]\nkind = \"receiver-unique-id\"\nsynthetic_value = \"abc\"\n// after\n[[replacements]]\nkind = \"receiver-unique-id\"\nsynthetic_value = \"A1B2C3D4E5F60718\"  # 16 ASCII bytes","handlingStrategy":"validation","validationCode":"fn replay_route_supported(audit: &CassetteAudit) -> bool {\n    audit.replacements.iter()\n        .filter(|r| r.kind == SanitizedIdentityKind::ReceiverUniqueId)\n        .all(|r| r.synthetic_value.len() == 16 && r.synthetic_value.is_ascii())\n}","typeGuard":"fn is_valid_receiver_uid(value: &[u8]) -> bool {\n    value.len() == 16 && value.is_ascii()\n}","tryCatchPattern":"match derive_replay_route(audit, route) {\n    Ok(r) => replay(r),\n    Err(e) if e.to_string().contains(\"sanitized Bolt receiver identity\") =>\n        eprintln!(\"cassette audit identity is malformed; re-record the fixture\"),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Never hand-edit audit `synthetic_value` entries; regenerate them via the sanitizer","Pin cassette schema versions between producer and consumer tools","Run the fixture crate's privacy/relationship verification before replay","Re-record fixtures rather than porting audits across sanitizer versions"],"tags":["fixture","replay","sanitization","device-identity"],"backgroundTag":"invalid-argument-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"}