AprilNEA/OpenLogi · error
cassette audit has no sanitized receiver identity
Error message
cassette audit has no sanitized receiver identity
What it means
`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.
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
Example fix
// before: replaying a direct cassette through the receiver path
let route = derive_replay_route(audit, &DeviceRoute::Direct { .. })?; // wrong path
// after: match route kind to the cassette's actual transport
match audit.transport { Bolt => derive_replay_route(audit, bolt_route), Direct => direct_route } Defensive patterns
Strategy: validation
Validate before calling
fn has_unique_replacement(audit: &CassetteAudit, kind: SanitizedIdentityKind) -> bool {
audit.replacements.iter().filter(|r| r.kind == kind).count() == 1
}
// require has_unique_replacement(audit, SanitizedIdentityKind::ReceiverUniqueId) before deriving a receiver route Try / catch
match unique_replacement(audit, SanitizedIdentityKind::ReceiverUniqueId) {
Ok(v) => derive_route(v),
Err(_) => eprintln!("no unique sanitized receiver identity; this cassette is not receiver-derived"),
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- sanitized Bolt receiver identity is not ASCII
- read-only HID++ case capture unexpectedly opened a raw…
- no sanitized channel candidate reproduced the captured…
- sanitized channel candidates reproduced the capture; target…
- sanitized Bolt receiver identity is not 16-byte ASCII
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/28169e7473679e6d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs:158
} => Ok(DeviceRoute::Direct {
vendor_id: *vendor_id,
product_id: *product_id,
}),
DeviceRoute::RawHid { .. } => {
bail!("raw HID routes are outside HID++ fixture case capture")
}
}
}
fn unique_replacement(audit: &HidCassetteAudit, kind: SanitizedIdentityKind) -> Result<&[u8]> {
let mut replacements = audit
.replacements
.iter()
.filter(|replacement| replacement.kind == kind);
let value = replacements
.next()
.map(|replacement| replacement.synthetic_value.as_slice())
.ok_or_else(|| anyhow::anyhow!("cassette audit has no sanitized receiver identity"))?;
if replacements.next().is_some() {
bail!("cassette audit has multiple sanitized receiver identities");
}
Ok(value)
}
#[cfg(test)]
mod tests {
use openlogi_device::write::FeatureEntry;
use openlogi_fixture::{
CassetteExchange, FIXTURE_SCHEMA_VERSION, HidCassette, ReportSupport, RequestMatch,
};
use openlogi_hid::FeatureType;
use openlogi_hid::recording::IdentityReplacement;
use super::*;
fn target(route: DeviceRoute, product_id: u16) -> TargetCandidate {View on GitHub (pinned to e846e6f4b4)