{"record":{"id":"28169e7473679e6d","repo":"AprilNEA/OpenLogi","slug":"cassette-audit-has-no-sanitized-receiver-identity","errorCode":null,"errorMessage":"cassette audit has no sanitized receiver identity","messagePattern":"cassette audit has no sanitized receiver identity","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs","lineNumber":158,"sourceCode":"        } => 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}\n\nfn unique_replacement(audit: &HidCassetteAudit, kind: SanitizedIdentityKind) -> Result<&[u8]> {\n    let mut replacements = audit\n        .replacements\n        .iter()\n        .filter(|replacement| replacement.kind == kind);\n    let value = replacements\n        .next()\n        .map(|replacement| replacement.synthetic_value.as_slice())\n        .ok_or_else(|| anyhow::anyhow!(\"cassette audit has no sanitized receiver identity\"))?;\n    if replacements.next().is_some() {\n        bail!(\"cassette audit has multiple sanitized receiver identities\");\n    }\n    Ok(value)\n}\n\n#[cfg(test)]\nmod tests {\n    use openlogi_device::write::FeatureEntry;\n    use openlogi_fixture::{\n        CassetteExchange, FIXTURE_SCHEMA_VERSION, HidCassette, ReportSupport, RequestMatch,\n    };\n    use openlogi_hid::FeatureType;\n    use openlogi_hid::recording::IdentityReplacement;\n\n    use super::*;\n\n    fn target(route: DeviceRoute, product_id: u16) -> TargetCandidate {","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs#L140-L176","documentation":"`unique_replacement` looks up the cassette audit's sanitized replacement of a given identity kind (e.g. `ReceiverUniqueId`) and requires exactly one match. If the audit contains no replacement of that kind, the lookup fails with this error — the replay route cannot be derived without the sanitized receiver identity.","triggerScenarios":"Calling `derive_replay_route` on a cassette whose audit `replacements` list lacks an entry for `ReceiverUniqueId` — the fixture never saw a Bolt/Unifying receiver unique id, or the audit was regenerated/stripped.","commonSituations":"Replaying a direct-connection (Bluetooth/wired) cassette as if it came through a Bolt receiver; auditing tools that dropped replacements they considered non-sensitive; schema drift between cassette versions.","solutions":["Use the correct replay path for the cassette type — a direct-connect cassette derives a direct route, not a receiver route","Re-record the fixture so the audit captures the receiver identity","Restore the missing `ReceiverUniqueId` replacement entry in the audit if it was erroneously removed","Check cassette schema/version compatibility between producer and consumer"],"exampleFix":"// before: replaying a direct cassette through the receiver path\nlet route = derive_replay_route(audit, &DeviceRoute::Direct { .. })?; // wrong path\n// after: match route kind to the cassette's actual transport\nmatch audit.transport { Bolt => derive_replay_route(audit, bolt_route), Direct => direct_route }","handlingStrategy":"validation","validationCode":"fn has_unique_replacement(audit: &CassetteAudit, kind: SanitizedIdentityKind) -> bool {\n    audit.replacements.iter().filter(|r| r.kind == kind).count() == 1\n}\n// require has_unique_replacement(audit, SanitizedIdentityKind::ReceiverUniqueId) before deriving a receiver route","typeGuard":null,"tryCatchPattern":"match unique_replacement(audit, SanitizedIdentityKind::ReceiverUniqueId) {\n    Ok(v) => derive_route(v),\n    Err(_) => eprintln!(\"no unique sanitized receiver identity; this cassette is not receiver-derived\"),\n}","preventionTips":["Match replay strategy to the cassette's actual transport (direct vs receiver)","Verify audits kept their replacements when regenerating or migrating cassettes","Use the fixture verification tooling to detect stripped audits early"],"tags":["fixture","replay","sanitization","audit"],"backgroundTag":"record-not-found","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"}