{"record":{"id":"f7286170c132d8c9","repo":"AprilNEA/OpenLogi","slug":"refusing-direct-fixture-capture-because-the-agent-endpoint","errorCode":null,"errorMessage":"refusing direct fixture capture because the agent endpoint is active or accepted a connection without completing a healthy handshake; this command uses the CLI's own HID permission and identity, so stop the OpenLogi agent before retrying","messagePattern":"refusing direct fixture capture because the agent endpoint is active or accepted a connection without completing a healthy handshake; this command uses the CLI's own HID permission and identity, so stop the OpenLogi agent before retrying","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/openlogi-cli/src/cmd/fixture/record_case.rs","lineNumber":314,"sourceCode":"    if args.name.trim().is_empty() {\n        bail!(\"--name must not be empty\");\n    }\n    if args.channel.trim().is_empty() {\n        bail!(\"--channel must not be empty\");\n    }\n    Ok(())\n}\n\nasync fn acquire_capture_ownership() -> Result<InstanceGuard> {\n    // The agent acquires this same lock before any HID I/O. An endpoint probe\n    // alone misses both early startup and a relaunch after the probe returns.\n    let guard = single_instance::acquire(\"agent.lock\").context(\n        \"refusing direct fixture capture: could not acquire agent.lock; \\\n         stop the OpenLogi agent and any other fixture capture before retrying\",\n    )?;\n    match tokio::time::timeout(AGENT_PROBE_TIMEOUT, client::connect()).await {\n        Ok(Err(ConnectError::Endpoint(error))) if endpoint_is_unreachable(&error) => Ok(guard),\n        Ok(Ok(_) | Err(ConnectError::Handshake(_) | ConnectError::Endpoint(_))) | Err(_) => bail!(\n            \"refusing direct fixture capture because the agent endpoint is active or accepted a \\\n             connection without completing a healthy handshake; this command uses the CLI's own \\\n             HID permission and identity, so stop the OpenLogi agent before retrying\"\n        ),\n    }\n}\n\nfn endpoint_is_unreachable(error: &io::Error) -> bool {\n    matches!(\n        error.kind(),\n        io::ErrorKind::NotFound | io::ErrorKind::ConnectionRefused\n    )\n}\n\nfn online_targets(inventories: &[DeviceInventory]) -> Vec<TargetCandidate> {\n    inventories\n        .iter()\n        .flat_map(|inventory| {","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/AprilNEA/OpenLogi/blob/e846e6f4b4405e33bd6a9aaf949a482ce34cb6d8/crates/openlogi-cli/src/cmd/fixture/record_case.rs#L296-L332","documentation":"`acquire_capture_ownership` takes the agent's `agent.lock` and then probes the agent's IPC endpoint. Direct fixture capture uses the CLI's own HID permission and identity, which would conflict with a running agent, so any reachable endpoint — or one that accepts a connection but fails a healthy handshake — causes this refusal.","triggerScenarios":"Running `openlogi fixture record-case` while the OpenLogi agent is running and its IPC socket is live; a stale agent process holding agent.lock with an accepting (but wedged) socket; an endpoint that accepts connections but fails the tarpc handshake within AGENT_PROBE_TIMEOUT.","commonSituations":"GUI-launched agent still running in the background (it self-relaunches ~20s later if left alive); a leftover agent from a crashed dev run; macOS LaunchServices-launched agent started by a previous `cargo run -p openlogi-desktop`.","solutions":["Stop the OpenLogi agent (quit it from the GUI or kill the openlogi-agent process), wait a moment so it does not self-relaunch, then retry","Remove any stale lock/socket state left by a crashed agent, then retry","If the agent keeps relaunching, disable autostart temporarily (e.g. OPENLOGI_DEV_AGENT=0 for dev runs) before recording","Use the mock/dev workflow instead of direct capture if you need the agent running concurrently"],"exampleFix":"// before\nopenlogi fixture record-case ...   # agent still running\n// after\npkill openlogi-agent   # and quit the GUI so it doesn't relaunch\nopenlogi fixture record-case ...","handlingStrategy":"validation","validationCode":"// stop the agent, then confirm the socket is gone before recording\npkill -x openlogi-agent || true\nif [ -S \"$(openlogi agent-socket-path 2>/dev/null)\" ]; then echo \"agent socket still live\"; exit 1; fi","typeGuard":null,"tryCatchPattern":"if err.to_string().contains(\"agent endpoint is active\") {\n    eprintln!(\"stop the OpenLogi agent, then retry the record command\");\n}","preventionTips":["Quit the GUI/agent before any direct fixture capture","Remember the agent self-relaunches ~20s after being killed if the GUI is alive (use OPENLOGI_DEV_AGENT=0 in dev)","Clean up stale agent.lock/socket files after crashes"],"tags":["ipc","fixture","agent-conflict","locking"],"backgroundTag":"address-already-in-use","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"}