{"record":{"id":"5af9fd954281563c","repo":"AprilNEA/OpenLogi","slug":"raw-hid-routes-are-outside-hid-fixture-case-capture","errorCode":null,"errorMessage":"raw HID routes are outside HID++ fixture case capture","messagePattern":"raw HID routes are outside HID\\+\\+ fixture case capture","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs","lineNumber":145,"sourceCode":"        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,\n            product_id,\n        } => 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}","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/record_case/replay.rs#L127-L163","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nopenlogi fixture record-case --target rawhid:1234:5678\n// after: target a HID++ device\nopenlogi fixture record-case --target direct:046d:b01e","handlingStrategy":"validation","validationCode":"// confirm the target resolves to a HID++ route before capture\nmatch route {\n    DeviceRoute::Bolt{..} | DeviceRoute::Unifying{..} | DeviceRoute::Direct{..} => ok(),\n    DeviceRoute::RawHid{..} => return Err(\"target is raw HID; not eligible for HID++ fixture capture\"),\n}","typeGuard":"fn is_hidpp_route(route: &DeviceRoute) -> bool {\n    !matches!(route, DeviceRoute::RawHid { .. })\n}","tryCatchPattern":null,"preventionTips":["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)"],"tags":["fixture","routing","unsupported","hidpp"],"backgroundTag":"unsupported-operation","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"}