AprilNEA/OpenLogi · error
read-only HID++ case capture unexpectedly opened a raw…
Error message
read-only HID++ case capture unexpectedly opened a raw writer; no fixture was written
What it means
`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.
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
Example fix
// before (write-typed op recorded as read-only case) record_case(Operation::SetDpi, read_only: true) // after record_case(Operation::SetDpi, read_only: false) // or choose a read-only op: record_case(Operation::GetDpi, read_only: true)
Defensive patterns
Strategy: validation
Validate before calling
// confirm the operation is genuinely read-only before a read-only capture
assert!(operation_catalog.is_read_only(op), "op {op:?} writes to the device; do not record as read-only"); Try / catch
if err.to_string().contains("unexpectedly opened a raw writer") {
eprintln!("operation writes to the device; record as a writable case instead");
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- capture failed with a host, open, disconnect, timeout…
- no sanitized channel candidate reproduced the captured…
- sanitized Bolt receiver identity is not 16-byte ASCII
- sanitized Unifying receiver identity is not four bytes
- raw HID routes are outside HID++ fixture case capture
AI-assisted analysis of AprilNEA/OpenLogi@e846e6f4b4 (2026-09-13).
Data as JSON: /api/errors/11eef8d7215229c9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/openlogi-cli/src/cmd/fixture/record_case/audit.rs:40
name: name.to_string(),
channel: channel.to_string(),
},
identity_plan,
);
render_build_report(index, &report);
if report.rejections.is_empty()
&& let Some(cassette) = report.cassette.clone()
{
candidates.push(SanitizedCandidate {
cassette,
audit: report.audit,
});
}
}
drop(recording);
if recorded_raw_writers {
bail!(
"read-only HID++ case capture unexpectedly opened a raw writer; no fixture was written"
);
}
Ok(candidates)
}
fn render_build_report(index: usize, report: &HidCassetteBuildReport) {
if report.is_committable() {
eprintln!("channel candidate {}: sanitizer accepted", index + 1);
} else {
eprintln!("channel candidate {}: sanitizer rejected", index + 1);
}
for replacement in &report.audit.replacements {
eprintln!(
" audit: {} replaced {} occurrence(s) with synthetic {}",
identity_kind_label(replacement.kind),
replacement.occurrences,
uppercase_hex(&replacement.synthetic_value)View on GitHub (pinned to e846e6f4b4)