AprilNEA / AprilNEA/OpenLogi

[Bug]: openlogi-agent panics in openlogi-async-hid win32 buffer when the device is removed mid-write (0x800701B1)

Open
#1,200 2 comments 0 reactions 0 assignees View on GitHub
area: hid platform: windows type: bug
Dominant language
Rust
Stars
21k
Forks
675
Avg merge
2d 5h
Merged PRs (30d)
172

Description

# [Bug]: openlogi-agent panics in openlogi-async-hid win32 buffer when the device is removed mid-write (0x800701B1)

- **Component:** Both (GUI + agent)
- **OpenLogi version:** 0.8.3 (`openlogi --version` → openlogi 0.8.3)
- **Operating system:** Windows
- **OS version & architecture:** Windows 11, build 26200 (x64)
- **Device model:** Logitech Lift Vertical Ergonomic Mouse, switched between Bluetooth-direct, Logi Bolt receiver, and wired USB during the session
- **How is the device connected?** Logi Bolt receiver (crash triggered while switching connections)

## Pre-flight checklist

- [x] I searched [existing issues](https://github.com/AprilNEA/OpenLogi/issues?q=is%3Aissue) and this is not a duplicate.
- [x] I am on the [latest release](https://github.com/AprilNEA/OpenLogi/releases/latest) or a recent `master` build.
- [x] I quit **Logi Options+** before running OpenLogi (the two apps fight over HID++ access and only one can own a receiver at a time).

## Affected area(s)

- [x] Device discovery / detection
- [x] Button remapping
- [x] DPI control
- [x] Other — agent stability: HID++ subsystem dead after the panic until a full restart

## What happened?

The agent **panics in `openlogi-async-hid`'s win32 buffer backend** when the device is removed/re-routed while an HID++ write is in flight. Reproduced twice within ~17 seconds while switching the Lift's connection (device was being moved between Bluetooth-direct and the Bolt receiver):

```text
2026-08-31T14:59:46.929584Z ERROR async_hid::backend::win32::buffer: Abandoned write failed: 指定不存在的设备。 (0x800701B1)
2026-08-31T14:59:46.929609Z ERROR openlogi_agent::logging: agent panicked: panicked at C:\Users\runneradmin\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\openlogi-async-hid-0.5.3-openlogi.1\src\backend\win32\buffer.rs:75:9:
I/O operation already pending
2026-08-31T14:59:46.929791Z WARN openlogi_agent::lifecycle: inventory watcher channel closed — marking enumeration unavailable
2026-08-31T15:00:03.848549Z ERROR async_hid::backend::win32::buffer: Abandoned write failed: 指定不存在的设备。 (0x800701B1)
2026-08-31T15:00:03.848608Z ERROR openlogi_agent::logging: agent panicked: panicked at C:\Users\runneradmin\.cargo\registry\src\index.crates.io-1949cf8c6b5b557f\openlogi-async-hid-0.5.3-openlogi.1\src\backend\win32\buffer.rs:75:9:
I/O operation already pending
```

`0x800701B1` is `ERROR_DEVICE_REMOVED` ("The device has been removed"); the panic payload is `I/O operation already pending` (the overlapped write was already completing when the abandoned-write path ran).

**Aftermath (worse than the crash itself):** the process survives, but the panicked worker takes the HID++ I/O with it — the session starts reporting empty captures, DPI writes fail with `DeviceUnreachable`, and the inventory keeps failing probes:

```text
WARN openlogi_agent_core::hardware: DPI write failed error=DeviceUnreachable { index: 255 }
WARN openlogi_device::inventory: node probe keeps failing — retiring its channel before reopen
INFO openlogi_device::session::gesture: control capture active index=1 gesture_sources=0 gesture_buttons=0 dpi_buttons=0 buttons=0 thumbwheel=false ...
```

No further HID++ activity is logged at all until the agent is fully restarted. Configuration that involves writing (e.g., gesture-divert arming, DPI changes) stops applying silently in this state.

## Steps to reproduce

1. Run OpenLogi 0.8.3 on Windows with a Lift (or any HID++ mouse) connected via Bluetooth-direct.
2. Generate HID++ writes — for example switch DPI in the GUI (the log shows `DPI action → writing to device dpi=2000`).
3. While a write is in flight, remove the device or change its connection (switch the mouse to the Bolt receiver, or unplug the receiver).
4. Observe the panic above in `~/.local/state/openlogi/agent..log` (or wherever your platform stores agent logs), followed by the degraded HID++ state.

## Expected behavior

A device disappearing mid-write should be handled like any other I/O error: the write is reported as failed and the channel is retired gracefully — **never a panic**. And if a panic does slip through, the process should not remain half-alive serving a dead HID++ subsystem; it should exit so the binary watchdog can restart it cleanly.

## Additional context

- Crate: `openlogi-async-hid 0.5.3-openlogi.1`, `src/backend/win32/buffer.rs:75`.
- The panic path is "Abandoned write failed" — a write abandoned when the device vanished, whose overlapped operation then reported already-pending. The abandoned-write path should tolerate completion/cancel races instead of `expect`/`panic!`.
- The agent log previously also showed `capture session ended unexpectedly, delaying re-arm` warnings on other days — this device's HID++ channel is evidently fragile across connection switches, and the panic turns a recoverable situation into a stuck agent.

## Diagnostics report

```markdown
### OpenLogi Diagnostics
**App**
- OpenLogi (GUI): v0.8.3 (release)
- Agent: v0.8.3 (connected at the time of the crash)
- OS: Windows (x86_64)
- Locale: en-US (UI: follow system)
- Accessibility: granted · Input hook: installed
- Launch at login: yes · Menu bar: yes · Update check: on

**Devices (1-2)**
- LIFT VERTICAL ERGONOMIC MOUSE — mouse
- Connection: Bluetooth-direct at session start, moved to Logi Bolt receiver (slot 2)
- Capabilities: buttons=yes, pointer=yes
- Model: b031 (model-ids: b031/0000/0000, ext-model: 02)
- G304 Lightspeed Wireless Gaming Mouse — mouse (present, unaffected)
```

## Logs

```text
# Both crash excerpts (full file: ~/.local/state/openlogi/agent.2026-08-31.log)
2026-08-31T14:59:46.929584Z ERROR async_hid::backend::win32::buffer: Abandoned write failed: 指定不存在的设备。 (0x800701B1)
2026-08-31T14:59:46.929609Z ERROR openlogi_agent::logging: agent panicked: panicked at ...openlogi-async-hid-0.5.3-openlogi.1\src\backend\win32\buffer.rs:75:9:
I/O operation already pending
2026-08-31T15:00:03.848549Z ERROR async_hid::backend::win32::buffer: Abandoned write failed: 指定不存在的设备。 (0x800701B1)
2026-08-31T15:00:03.848608Z ERROR openlogi_agent::logging: agent panicked: panicked at ...\buffer.rs:75:9:
I/O operation already pending
# Degraded state afterwards
2026-08-31T14:37:51.226121Z WARN openlogi_device::inventory: node probe keeps failing — retiring its channel before reopen
2026-08-31T14:41:07.836064Z INFO openlogi_agent_core::runtime::hook: gesture click → executing bound action button=Back action=Screenshot
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with openlogi-async-hid's src/backend/win32/buffer.rs at line 75 and trace the abandoned-write path, including completion and cancellation races. Reproduce a device removal during an HID++ write on Windows, then verify that the error is handled without a panic and that the channel or agent recovers cleanly.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
58/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.