{"record":{"id":"11eef8d7215229c9","repo":"AprilNEA/OpenLogi","slug":"read-only-hid-case-capture-unexpectedly-opened-a-raw-writer","errorCode":null,"errorMessage":"read-only HID++ case capture unexpectedly opened a raw writer; no fixture was written","messagePattern":"read-only HID\\+\\+ case capture unexpectedly opened a raw writer; no fixture was written","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/record_case/audit.rs","lineNumber":40,"sourceCode":"                name: name.to_string(),\n                channel: channel.to_string(),\n            },\n            identity_plan,\n        );\n        render_build_report(index, &report);\n        if report.rejections.is_empty()\n            && let Some(cassette) = report.cassette.clone()\n        {\n            candidates.push(SanitizedCandidate {\n                cassette,\n                audit: report.audit,\n            });\n        }\n    }\n    drop(recording);\n\n    if recorded_raw_writers {\n        bail!(\n            \"read-only HID++ case capture unexpectedly opened a raw writer; no fixture was written\"\n        );\n    }\n    Ok(candidates)\n}\n\nfn render_build_report(index: usize, report: &HidCassetteBuildReport) {\n    if report.is_committable() {\n        eprintln!(\"channel candidate {}: sanitizer accepted\", index + 1);\n    } else {\n        eprintln!(\"channel candidate {}: sanitizer rejected\", index + 1);\n    }\n    for replacement in &report.audit.replacements {\n        eprintln!(\n            \"  audit: {} replaced {} occurrence(s) with synthetic {}\",\n            identity_kind_label(replacement.kind),\n            replacement.occurrences,\n            uppercase_hex(&replacement.synthetic_value)","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/record_case/audit.rs#L22-L58","documentation":"`sanitize_recording_with_plan` audits the captured recording and asserts a read-only HID++ case capture never opened a raw writer. If the audit finds raw-writer activity recorded during the capture, the recording cannot be a valid read-only fixture and the error aborts before writing anything.","triggerScenarios":"A capture declared as read-only HID++ recorded raw HID output reports (raw writer opens) — e.g. the operation touched a write-only/raw path instead of a pure HID++ read, or the capture logic misclassified a write operation as read-only.","commonSituations":"Recording a case whose operation actually writes to the device (DPI write, profile set) while the case is declared read-only; a firmware/device where a nominally read command triggers an output report; a bug in the operation catalog tagging an operation read-only incorrectly.","solutions":["Record the case with the correct operation kind (a writable case) rather than declaring it read-only","Pick a genuinely read-only operation for this capture (feature enumeration, config reads)","If you believe the operation is read-only but the device emits a write, file/inspect the operation catalog entry in openlogi-core for a misclassification"],"exampleFix":"// before (write-typed op recorded as read-only case)\nrecord_case(Operation::SetDpi, read_only: true)\n// after\nrecord_case(Operation::SetDpi, read_only: false)\n// or choose a read-only op:\nrecord_case(Operation::GetDpi, read_only: true)","handlingStrategy":"validation","validationCode":"// confirm the operation is genuinely read-only before a read-only capture\nassert!(operation_catalog.is_read_only(op), \"op {op:?} writes to the device; do not record as read-only\");","typeGuard":null,"tryCatchPattern":"if err.to_string().contains(\"unexpectedly opened a raw writer\") {\n    eprintln!(\"operation writes to the device; record as a writable case instead\");\n}","preventionTips":["Keep the operation catalog's read/write classification accurate","Only mark captures read-only for pure query operations","Never hand-edit fixture audit data that toggles capture kind"],"tags":["fixture","sanitization","invariant-violation","hidpp"],"backgroundTag":"internal-invariant-violation","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"}