AprilNEA/OpenLogi · error
raw HID routes are outside HID++ fixture case capture
Error message
raw HID routes are outside HID++ fixture case capture
What it means
`derive_replay_route` only supports Bolt, Unifying, and Direct routes for HID++ fixture case capture. A RawHid route means the capture targeted a raw HID device outside the HID++ fixture model, so route derivation refuses instead of producing a meaningless fixture route.
Solutions
- Record the case against a HID++-capable device (check with `openlogi list` that it routes as Bolt/Unifying/Direct)
- If the device is HID++-capable but enumerated as RawHid, add/fix its driver metadata in openlogi-device-registry
- Skip fixture capture for genuinely raw-HID devices — they are outside this fixture model
Example fix
// before openlogi fixture record-case --target rawhid:1234:5678 // after: target a HID++ device openlogi fixture record-case --target direct:046d:b01e
Defensive patterns
Strategy: validation
Validate before calling
// confirm the target resolves to a HID++ route before capture
match route {
DeviceRoute::Bolt{..} | DeviceRoute::Unifying{..} | DeviceRoute::Direct{..} => ok(),
DeviceRoute::RawHid{..} => return Err("target is raw HID; not eligible for HID++ fixture capture"),
} Type guard
fn is_hidpp_route(route: &DeviceRoute) -> bool {
!matches!(route, DeviceRoute::RawHid { .. })
} Prevention
- Check `openlogi list` route type before recording a device
- Register HID++-capable devices in openlogi-device-registry so they don't fall back to RawHid
- Don't attempt fixture capture for raw-HID-only devices (bootloader/DFU modes)
When it happens
Trigger: Running fixture case capture/replay against a device whose route resolves to RawHid — e.g. recording a case for a non-HID++ (raw HID) device or a device enumerated without a HID++ driver mapping.
Common situations: Pointing the recorder at a device that exposes only a raw HID interface; a device missing from the openlogi-device-registry so it falls back to RawHid; a USB device in bootloader/DFU mode presenting a raw interface.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- capture failed with a host, open, disconnect, timeout…
- read-only HID++ case capture unexpectedly opened a raw…
- no sanitized channel candidate reproduced the captured…
- SmartShift sensitivity write not applied: requested
- SmartShift mode changed unexpectedly: was
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/5af9fd954281563c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs:145
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,
})
}
DeviceRoute::Direct {
vendor_id,
product_id,
} => 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)
}View on GitHub (pinned to e846e6f4b4)