AprilNEA/OpenLogi · error
sanitized Bolt receiver identity is not 16-byte ASCII
Error message
sanitized Bolt receiver identity is not 16-byte ASCII
What it means
`derive_replay_route` rebuilds the concrete device route from sanitized audit data. For a Bolt route it reads the sanitized ReceiverUniqueId replacement, which must be exactly 16 ASCII bytes to form a valid receiver UID; otherwise the sanitized fixture data is malformed and the error is thrown.
Solutions
- Re-record the fixture so the sanitizer regenerates a valid 16-byte ASCII receiver UID
- Inspect the fixture's audit section and correct the ReceiverUniqueId replacement to exactly 16 ASCII bytes
- Regenerate sanitized identities via the openlogi-fixture synthetic identity policy instead of editing them manually
Example fix
// before (hand-edited audit) "receiver_unique_id": "ABC123" // 6 bytes // after "receiver_unique_id": "A1B2C3D4E5F6A7B8" // 16 ASCII bytes
Defensive patterns
Strategy: validation
Validate before calling
fn valid_bolt_uid(v: &[u8]) -> bool { v.len() == 16 && v.is_ascii() }
// check before replaying a Bolt fixture
assert!(valid_bolt_uid(&audit.receiver_unique_id), "sanitized Bolt UID must be 16 ASCII bytes"); Type guard
fn valid_bolt_uid(v: &[u8]) -> bool {
v.len() == 16 && v.is_ascii()
} Prevention
- Never hand-edit sanitized identity fields in fixtures
- Regenerate identities through the openlogi-fixture synthetic identity policy
- Validate fixture audit JSON after sanitizer version changes
When it happens
Trigger: Replaying a Bolt-routed fixture whose audit identity replacement for ReceiverUniqueId is missing, the wrong length (not 16 bytes), or contains non-ASCII bytes — e.g. a fixture produced by an older/buggy sanitizer or hand-edited audit JSON.
Common situations: Hand-editing sanitized fixture identities; a sanitizer change altering the replacement format; a corrupted fixture cache; using a fixture recorded against a different identity policy version.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- sanitized Unifying receiver identity is not four bytes
- --name must not be empty
- --channel must not be empty
- read-only HID++ case capture unexpectedly opened a raw…
- no sanitized channel candidate reproduced the captured…
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/c99dcbced62dc0f4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs:117
receiver_slots,
}],
channels: vec![ReplayChannel {
id: cassette.channel.clone(),
connection: ChannelConnection::Connected,
report_support: cassette.report_support,
}],
}
}
fn derive_replay_route(
selected_route: &DeviceRoute,
audit: &HidCassetteAudit,
) -> Result<DeviceRoute> {
match selected_route {
DeviceRoute::Bolt { slot, .. } => {
let value = unique_replacement(audit, SanitizedIdentityKind::ReceiverUniqueId)?;
if value.len() != 16 || !value.is_ascii() {
bail!("sanitized Bolt receiver identity is not 16-byte ASCII");
}
let receiver_uid = std::str::from_utf8(value)
.map_err(|_| anyhow::anyhow!("sanitized Bolt receiver identity is not ASCII"))?
.to_string();
Ok(DeviceRoute::Bolt {
receiver_uid,
slot: *slot,
})
}
DeviceRoute::Unifying { slot, .. } => {
let value = unique_replacement(audit, SanitizedIdentityKind::ReceiverSerialNumber)?;
if value.len() != 4 {
bail!("sanitized Unifying receiver identity is not four bytes");
}
Ok(DeviceRoute::Unifying {
receiver_uid: uppercase_hex(value),
slot: *slot,
})View on GitHub (pinned to e846e6f4b4)