-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Summary
The fix in PR #88 for issue SpanPanel/span#156 is incomplete. While RemoteProtocolError is now handled correctly, parallel API requests in get_all_data() can still fail with unhandled exceptions when one request destroys the shared client while others are in-flight.
Related
- Original issue: Add retry logic for httpx RemoteProtocolError: Server disconnected without sending a response span#156
- Original fix: Recognize panel Keep-Alive at 5 sec, Handle httpx.RemoteProtocolError… #88
Problem
When get_all_data() runs parallel requests via asyncio.gather():
get_status()usesrequires_auth=False→ gets its own client (OK)get_panel_state(),get_circuits(),get_storage_soe()userequires_auth=True→ shareself._client
When a stale connection causes RemoteProtocolError:
- One task catches it and destroys
self._clientvia__aexit__ - Other parallel tasks still have in-flight requests using the same underlying httpx client
- Those requests fail with
ReadError,WriteError, orCloseError(all subclasses ofNetworkError) - These exceptions are not caught by the retry loop
- They bubble up and get wrapped as
SpanPanelAPIError("Unexpected error: {e}") - Since these exceptions often have empty messages, logs show:
"Unexpected error: "
Evidence
Home Assistant logs show two types of errors:
ERROR: Unexpected error: Server disconnected without sending a response. ← RemoteProtocolError (handled)
ERROR: Unexpected error: ← ReadError/WriteError (unhandled, empty message)
The empty error messages are caused by httpx exceptions with no message:
>>> str(httpx.ReadError(''))
''
>>> str(httpx.WriteError(''))
''Exception Hierarchy
httpx.TransportError
├── httpx.NetworkError
│ ├── httpx.ReadError ← NOT HANDLED
│ ├── httpx.WriteError ← NOT HANDLED
│ └── httpx.CloseError ← NOT HANDLED
└── httpx.ProtocolError
└── httpx.RemoteProtocolError ← HANDLED in PR #88
Suggested Fix
- Catch
httpx.TransportError(or at minimumhttpx.NetworkError) instead of justRemoteProtocolError:
except (httpx.RemoteProtocolError, httpx.NetworkError):
# Server closed connection or network error - connection pool likely corrupted
# Destroy client to force fresh connection pool on retry
...-
Consider adding locking around client destruction/recreation to prevent race conditions, or
-
Use separate clients for parallel requests instead of sharing
self._client
Environment
- span-panel-api: 1.1.14
- span (integration): 1.30b1 (manifest shows 1.3.0)
- Home Assistant: 2024.x
- Multiple SPAN panels (which may increase likelihood of hitting this race condition)
This issue was written by Claude (claude-opus-4-5-20250121) via Claude Code, based on analysis of the installed code and error logs.
🤖 Generated with Claude Code