{"record":{"id":"4478166b59239584","repo":"AprilNEA/OpenLogi","slug":"raw-hid-devices-support-profile-only-contributions","errorCode":null,"errorMessage":"raw-HID devices support profile-only contributions","messagePattern":"raw-HID devices support profile-only contributions","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/contribute.rs","lineNumber":352,"sourceCode":"            let ordinal = classify_synthetic_profile_identity(\n                SyntheticIdentityKind::UnifyingReceiverRoute,\n                receiver_uid,\n            )?;\n            let serial =\n                generate_synthetic_identity(SyntheticIdentityKind::UnifyingReceiverSerial, ordinal)\n                    .as_bytes()\n                    .ok_or_else(|| anyhow!(\"could not derive synthetic Unifying serial\"))?\n                    .to_vec();\n            plan.insert(SanitizedIdentityKind::ReceiverSerialNumber, serial)?;\n            selected_model(profile, selected_route, *slot)?\n        }\n        DeviceRoute::Direct { .. } => selected_model(\n            profile,\n            selected_route,\n            openlogi_core::hid::DIRECT_DEVICE_INDEX,\n        )?,\n        DeviceRoute::RawHid { .. } => {\n            bail!(\"raw-HID devices support profile-only contributions\")\n        }\n    };\n    add_model_identities(&mut plan, model)?;\n    Ok(plan)\n}\n\nfn selected_model<'a>(\n    profile: &'a DeviceProfile,\n    route: &DeviceRoute,\n    slot: u8,\n) -> Result<&'a DeviceModelInfo> {\n    profile\n        .inventories\n        .iter()\n        .find(|inventory| {\n            inventory.paired.iter().any(|device| {\n                DeviceRoute::device_route_for(inventory, device.slot).as_ref() == Some(route)\n            })","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/contribute.rs#L334-L370","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before: full capture on a raw-HID route\n$ openlogi fixture contribute --id my-fixture --device 046d:c52b --output output/my-fixture\nError: raw-HID devices support profile-only contributions\n// after: use the supported contribution mode\n$ openlogi fixture contribute --id my-fixture --device 046d:c52b --output output/my-fixture --profile-only","handlingStrategy":"validation","validationCode":"// Check the device route before requesting full capture\nlet route = device.route();\nif matches!(route, DeviceRoute::RawHid { .. }) {\n    eprintln!(\"device is raw-HID: rerun with --profile-only\");\n    std::process::exit(2);\n}","typeGuard":"fn supports_full_capture(route: &DeviceRoute) -> bool {\n    !matches!(route, DeviceRoute::RawHid { .. })\n}","tryCatchPattern":"match contribute_result {\n    Err(e) if e.to_string().contains(\"profile-only contributions\") => {\n        eprintln!(\"raw-HID device: rerun with --profile-only\");\n    }\n    Err(e) => return Err(e),\n    Ok(v) => println!(\"{v:?}\"),\n}","preventionTips":["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"],"tags":["fixtures","hid","cli","unsupported-operation"],"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"}