AprilNEA/OpenLogi · error
raw-HID devices support profile-only contributions
Error message
raw-HID devices support profile-only contributions
What it means
`identity_plan` builds the sanitized identity plan required for full cassette capture, but raw-HID routes carry no HID++ receiver/slot model information, so no per-device identity can be derived from them. The CLI therefore rejects full cassette capture for raw-HID devices and directs the user to a profile-only contribution, which does not need cassette identity relationships.
Solutions
- Rerun the contribution with `--profile-only`, which is the supported path for raw-HID devices
- Check `openlogi list` to see how the device is routed; if it should be a direct HID++ device, verify it is connected via a supported transport (direct USB/BT or Bolt/Unifying receiver)
- Select a different `--device` selector that resolves to a Direct/Bolt/Unifying route if the device offers multiple interfaces
- Update device-registry metadata/driver definitions if a legitimately HID++-capable device is being misclassified as raw-HID
Example fix
// before: full capture on a raw-HID route $ openlogi fixture contribute --id my-fixture --device 046d:c52b --output output/my-fixture Error: raw-HID devices support profile-only contributions // after: use the supported contribution mode $ openlogi fixture contribute --id my-fixture --device 046d:c52b --output output/my-fixture --profile-only
Defensive patterns
Strategy: validation
Validate before calling
// Check the device route before requesting full capture
let route = device.route();
if matches!(route, DeviceRoute::RawHid { .. }) {
eprintln!("device is raw-HID: rerun with --profile-only");
std::process::exit(2);
} Type guard
fn supports_full_capture(route: &DeviceRoute) -> bool {
!matches!(route, DeviceRoute::RawHid { .. })
} Try / catch
match contribute_result {
Err(e) if e.to_string().contains("profile-only contributions") => {
eprintln!("raw-HID device: rerun with --profile-only");
}
Err(e) => return Err(e),
Ok(v) => println!("{v:?}"),
} Prevention
- Run `openlogi list` first and check each device's route type before contributing
- Connect HID++ devices via a supported transport (Bolt/Unifying receiver, Bluetooth-direct, or wired direct)
- Use `--profile-only` by default for devices known to be raw-HID only
- Keep device-registry metadata current so capable devices aren't misclassified as raw-HID
When it happens
Trigger: Running `openlogi fixture contribute` (full capture, not `--profile-only`) while the selected `--device` resolves to a `DeviceRoute::RawHid` route — i.e. the device was enumerated as a plain raw HID interface rather than via Bolt/Unifying receiver or a direct HID++ connection.
Common situations: Device attached through a generic/vendor-specific interface that only exposes raw HID; receiver-less devices that the registry doesn't recognize as HID++-capable; selecting the wrong interface of a multi-interface device with `--device`; driver/registry metadata missing so the device falls back to raw-HID classification.
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
- the selected device has no stable synthetic identity for…
- the selected direct-capture target does not match the…
- resumable fixture cases contain a non-UTF-8 entry
- resumable fixture cases contain unexpected file
- fixture directory has no UTF-8 synthetic ID
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/4478166b59239584.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/contribute.rs:352
let ordinal = classify_synthetic_profile_identity(
SyntheticIdentityKind::UnifyingReceiverRoute,
receiver_uid,
)?;
let serial =
generate_synthetic_identity(SyntheticIdentityKind::UnifyingReceiverSerial, ordinal)
.as_bytes()
.ok_or_else(|| anyhow!("could not derive synthetic Unifying serial"))?
.to_vec();
plan.insert(SanitizedIdentityKind::ReceiverSerialNumber, serial)?;
selected_model(profile, selected_route, *slot)?
}
DeviceRoute::Direct { .. } => selected_model(
profile,
selected_route,
openlogi_core::hid::DIRECT_DEVICE_INDEX,
)?,
DeviceRoute::RawHid { .. } => {
bail!("raw-HID devices support profile-only contributions")
}
};
add_model_identities(&mut plan, model)?;
Ok(plan)
}
fn selected_model<'a>(
profile: &'a DeviceProfile,
route: &DeviceRoute,
slot: u8,
) -> Result<&'a DeviceModelInfo> {
profile
.inventories
.iter()
.find(|inventory| {
inventory.paired.iter().any(|device| {
DeviceRoute::device_route_for(inventory, device.slot).as_ref() == Some(route)
})View on GitHub (pinned to e846e6f4b4)