{"record":{"id":"58bf45ea0481dfad","repo":"AprilNEA/OpenLogi","slug":"unsupported-hid-report-id-04x","errorCode":null,"errorMessage":"unsupported HID++ report id {:#04x}","messagePattern":"unsupported HID\\+\\+ report id (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/openlogi-hid/src/transport/windows.rs","lineNumber":265,"sourceCode":"    fn vendor_id(&self) -> u16 {\n        self.info.vendor_id\n    }\n\n    fn product_id(&self) -> u16 {\n        self.info.product_id\n    }\n\n    async fn write_report(&self, src: &[u8]) -> Result<usize, Box<dyn Error + Send + Sync>> {\n        if !self.device_io.allows_io() {\n            return Err(super::device_io_error());\n        }\n        let endpoint = match src.first().copied().and_then(endpoint_for_report_id) {\n            Some(ReportEndpoint::Short) => self.short.as_ref(),\n            Some(ReportEndpoint::Long) => Some(&self.long),\n            _ => None,\n        }\n        .ok_or_else(|| {\n            io::Error::new(\n                io::ErrorKind::Unsupported,\n                format!(\n                    \"unsupported HID++ report id {:#04x}\",\n                    src.first().copied().unwrap_or_default()\n                ),\n            )\n        })?;\n\n        if !self.device_io.allows_io() {\n            return Err(super::device_io_error());\n        }\n        let result = endpoint.write_report(src).await;\n        if let Err(e) = &result\n            && is_permanent_disconnect(e.as_ref())\n        {\n            self.mark_disconnected();\n        }\n        result","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-hid/src/transport/windows.rs#L247-L283","documentation":"On Windows, the composite HID channel routes each outgoing report by its first byte (the report id) to either the short or the long HID++ endpoint via `endpoint_for_report_id`. If the report id is unknown to that mapping, no endpoint is selected and an `io::ErrorKind::Unsupported` error carrying this message is returned from `write_report`. It is a programming/protocol error rather than a runtime device condition.","triggerScenarios":"Calling `write_report` with a buffer whose first byte is not a recognized HID++ report id (neither the short 0x10 nor long 0x11 report, or any id missing from `endpoint_for_report_id`); also triggered when the buffer is empty (`src.first()` is `None`, falling into the `_ => None` arm with report id shown as 0x00).","commonSituations":"Constructing a raw HID++ packet by hand with a wrong report id; passing a vendor/custom feature report to the HID++ channel; a protocol-layer regression sending zero-length buffers; copying report formats from non-HID++ (consumer-page) devices.","solutions":["Prefix the payload with the correct HID++ report id: 0x10 for short (7-byte) or 0x11 for long (20-byte) reports.","Verify the buffer is non-empty and its length matches the report id before writing.","Use the crate's HID++ report constructors instead of hand-built byte arrays.","Log the full report (`{:#04x}` shows the offending id) and compare against `endpoint_for_report_id`'s supported set."],"exampleFix":"// before — raw payload without a HID++ report id\nlet mut report = vec![0x00; 7];\nreport[1..].copy_from_slice(&payload);\nbackend.write_report(&report).await?; // error: unsupported HID++ report id 0x00\n\n// after — proper short HID++ report\nlet mut report = vec![0x10; 7];\nreport[1..].copy_from_slice(&payload);\nbackend.write_report(&report).await?;","handlingStrategy":"validation","validationCode":"const SHORT_REPORT: u8 = 0x10;\nconst LONG_REPORT: u8 = 0x11;\nfn assert_hidpp_report(report: &[u8]) -> std::io::Result<()> {\n    match report.first() {\n        Some(&SHORT_REPORT) if report.len() == 7 => Ok(()),\n        Some(&LONG_REPORT) if report.len() == 20 => Ok(()),\n        other => Err(std::io::Error::new(\n            std::io::ErrorKind::Unsupported,\n            format!(\"bad HID++ report id/length: {:?} len={}\", other, report.len()),\n        )),\n    }\n}","typeGuard":"fn is_short_hidpp(report: &[u8]) -> bool { report.first() == Some(&0x10) && report.len() == 7 }\nfn is_long_hidpp(report: &[u8]) -> bool { report.first() == Some(&0x11) && report.len() == 20 }","tryCatchPattern":null,"preventionTips":["Always build reports via the hidpp crate's constructors, never raw byte arrays.","Validate report id (0x10/0x11) and length before every write in debug builds.","Guard against empty buffers — an empty first byte renders as 0x00 in this error."],"tags":["windows","hidpp","protocol","report-id"],"backgroundTag":"invalid-argument-format","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"}