Skip to content

[WIP] Fix UtilResponse to distinguish WebSocket completion from errors#30

Closed
Copilot wants to merge 1 commit into
mainfrom
copilot/fix-websocket-completion-handling
Closed

[WIP] Fix UtilResponse to distinguish WebSocket completion from errors#30
Copilot wants to merge 1 commit into
mainfrom
copilot/fix-websocket-completion-handling

Conversation

Copilot AI commented Jun 15, 2026

Copy link
Copy Markdown

Thanks for asking me to work on this. I will get started on it and keep this PR's description up to date as I form a plan and make progress.


This section details on the original issue you should resolve

<issue_title>UtilResponse cannot distinguish a clean WebSocket completion from an error/abnormal close</issue_title>
<issue_description>In mistapi/device_utils/__tools/__ws_wrapper.py (v0.62.0), a completed UtilResponse exposes no signal that the device-utility WebSocket errored, closed abnormally, or failed to start — so a consumer cannot tell a confirmed result from an unconfirmed one.

Where the information is lost

  • WebSocketWrapper.start() wires ws.on_error(lambda error: LOGGER.error("Error: %s", error)) — the error is logged and discarded.
  • WebSocketWrapper._on_close(code, msg) logs the close code but stores nothing on the UtilResponse.
  • start_with_trigger._run(): when the WS factory returns None, the trigger raises, or the trigger is non-200, it calls self.util_response._closed.set() (→ done=True) without setting ws_required or recording why it ended.

Impact

After await / wait(), a UtilResponse only carries trigger_api_response, ws_required, ws_data, done. As a result these three outcomes are indistinguishable to a caller:

Scenario trigger_api_response ws_required ws_data done
Healthy trigger-only command 200 False [] True
WS-backed command, WebSocket failed to start 200 False [] True
WS-backed command, WebSocket errored mid-stream 200 True partial True

A caller that persists a durable "executed/confirmed" record (e.g. an approval or audit flow) can therefore record an unconfirmed device action as confirmed.

Proposed change (additive, backward-compatible)

  1. UtilResponse.__init__: add self.ws_error: str | None = None and self.ws_close_code: int | None = None.
  2. WebSocketWrapper.start(): replace the discard lambda with a handler that records self.util_response.ws_error = str(error) (still logs).
  3. WebSocketWrapper._on_close(self, code, msg): set self.util_response.ws_close_code = code; if code indicates an abnormal close, also set ws_error.
  4. start_with_trigger._run() failure fall-throughs: set self.util_response.ws_error = "<reason>" (e.g. "WebSocket factory returned None", f"trigger error: {e}", f"trigger failed: {status_code}") before _closed.set().

Then ws_error is not None is a reliable "did not cleanly confirm" signal, and happy paths are unchanged (ws_error stays None). A PR implementing this follows.</issue_description>

Comments on the Issue (you are @copilot in this section)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

UtilResponse cannot distinguish a clean WebSocket completion from an error/abnormal close

2 participants