Commit b39ef1b
fix: surface WebSocket close to tool calls instead of hanging (#1773)
* fix: surface WebSocket close to tool calls instead of hanging (#1721)
When the WebSocket to Home Assistant closed while a command awaited its
response, the pending future was cancelled; the resulting CancelledError
escaped every except-Exception handler and reached the MCP SDK, which
suppressed the response entirely. The MCP client then hung until its own
timeout (4 minutes in Claude clients) with only a bare 'WebSocket
connection closed' log line to go on.
- Fail pending request/event futures with HomeAssistantConnectionError
(carrying the close code/reason) instead of cancelling them, so tools
raise a structured error immediately.
- Log the close code and reason (e.g. 1009 message-too-big) instead of
discarding them; WARNING for abnormal closes.
- Raise the client max_size 20MB -> 64MB, matching the Supervisor's own
Core-connection limit: config/entity_registry/list arrives as one
frame that scales with entity count (no pagination in the HA WS API)
and overflowed 20MB on a ~6.4k-entity instance.
- Chunk config/entity_registry/get_entries alias enrichment (500 ids per
call) so its response frame stays bounded on large instances.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test: use future.result() to re-raise, satisfying py/ineffectual-statement
Bare 'await request_future' statements tripped CodeQL's
py/ineffectual-statement (await of a Name reads as an expression with no
effect). The futures are already done after reset_connection sets the
exception, so result() re-raises the stored exception directly -- a call
expression the rule does not flag, and a more direct assertion of the
state contract.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: retrieve orphaned event-future exception; surface alias-fetch warnings
Review-driven hardening on top of the #1721 fix:
- send_command_with_event: a connection drop during the result phase now
retrieves event_future's exception (reset_connection fails BOTH futures;
only result_future was awaited), preventing asyncio's ERROR-level
'Future exception was never retrieved' on the exact path this PR makes
diagnosable. Regression-tested red/green via asyncio's retrieved-flag.
- _fetch_entity_aliases now returns (aliases_map, warnings): failed
get_entries chunks surface as a top-level warning in search results
instead of silently returning success with missing aliases.
- Close the untested branches flagged by review: self-initiated close
(sent 1009 -- the literal #1721 trigger), WARNING-vs-INFO level split,
abrupt no-close-frame drop, generic handler exception teardown,
max_size wiring into websockets.connect, CancelledError propagation in
the chunk loop, malformed success payload tolerance.
- Docstring: drop hardcoded 500 duplicating _GET_ENTRIES_CHUNK_SIZE.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: kingpanther13 <kingpanther13@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent 97ec188 commit b39ef1b
4 files changed
Lines changed: 678 additions & 39 deletions
File tree
- src/ha_mcp
- client
- tools/smart_search
- tests/src/unit
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
33 | 42 | | |
34 | 43 | | |
35 | 44 | | |
| |||
109 | 118 | | |
110 | 119 | | |
111 | 120 | | |
112 | | - | |
113 | | - | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
114 | 129 | | |
115 | 130 | | |
116 | 131 | | |
117 | 132 | | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
118 | 146 | | |
119 | 147 | | |
120 | | - | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
121 | 153 | | |
122 | 154 | | |
123 | 155 | | |
124 | 156 | | |
125 | | - | |
| 157 | + | |
126 | 158 | | |
127 | 159 | | |
128 | 160 | | |
| |||
144 | 176 | | |
145 | 177 | | |
146 | 178 | | |
147 | | - | |
| 179 | + | |
148 | 180 | | |
149 | | - | |
| 181 | + | |
150 | 182 | | |
151 | 183 | | |
152 | 184 | | |
| |||
293 | 325 | | |
294 | 326 | | |
295 | 327 | | |
296 | | - | |
297 | | - | |
298 | | - | |
| 328 | + | |
299 | 329 | | |
300 | 330 | | |
301 | 331 | | |
| |||
390 | 420 | | |
391 | 421 | | |
392 | 422 | | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
393 | 428 | | |
394 | 429 | | |
395 | 430 | | |
| |||
400 | 435 | | |
401 | 436 | | |
402 | 437 | | |
403 | | - | |
404 | | - | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
405 | 457 | | |
| 458 | + | |
406 | 459 | | |
407 | 460 | | |
408 | | - | |
| 461 | + | |
409 | 462 | | |
410 | 463 | | |
411 | 464 | | |
| |||
649 | 702 | | |
650 | 703 | | |
651 | 704 | | |
652 | | - | |
| 705 | + | |
653 | 706 | | |
654 | 707 | | |
| 708 | + | |
| 709 | + | |
| 710 | + | |
| 711 | + | |
| 712 | + | |
| 713 | + | |
655 | 714 | | |
656 | 715 | | |
657 | 716 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
15 | 20 | | |
16 | 21 | | |
17 | 22 | | |
| |||
144 | 149 | | |
145 | 150 | | |
146 | 151 | | |
147 | | - | |
| 152 | + | |
148 | 153 | | |
149 | 154 | | |
150 | 155 | | |
151 | | - | |
152 | | - | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
153 | 168 | | |
154 | 169 | | |
155 | 170 | | |
156 | | - | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
169 | 199 | | |
170 | | - | |
171 | | - | |
172 | | - | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
173 | 203 | | |
174 | 204 | | |
175 | | - | |
176 | | - | |
177 | | - | |
178 | | - | |
179 | | - | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
180 | 233 | | |
181 | | - | |
| 234 | + | |
182 | 235 | | |
183 | 236 | | |
184 | 237 | | |
| |||
223 | 276 | | |
224 | 277 | | |
225 | 278 | | |
226 | | - | |
| 279 | + | |
| 280 | + | |
227 | 281 | | |
228 | 282 | | |
229 | 283 | | |
| |||
0 commit comments