-
Notifications
You must be signed in to change notification settings - Fork 13
Closed
NickBorgersOnLowSecurityNode/span
#1Description
Problem
The SPAN Panel integration frequently fails with the error:
Server disconnected without sending a response.
This occurs even when the SPAN panels are fully reachable and responding normally to direct HTTP requests.
Evidence
Integration logs show repeated failures:
ERROR custom_components.span_panel.span_panel_api: Failed to get all panel data: Unexpected error: Server disconnected without sending a response.
WARNING custom_components.span_panel.span_panel: Panel update failed (Unexpected error: Server disconnected without sending a response.); marking offline
But the panels respond fine to direct requests:
$ ping -c 2 10.212.101.111
2 packets transmitted, 2 packets received, 0% packet loss
$ curl -sk -o /dev/null -w '%{http_code}' https://10.212.101.111/api/v1/panel
412 # Expected without auth tokenRoot Cause
This is a well-documented httpx connection pooling issue:
- httpx maintains a connection pool for HTTP keep-alive
- The SPAN panel closes idle connections after its keep-alive timeout expires
- httpx attempts to reuse a connection that was already closed server-side
- Result:
RemoteProtocolError: Server disconnected without sending a response
This is not a network issue - it's a client-side connection pool race condition.
Impact
When this error occurs repeatedly:
- The integration marks panels as offline despite them being reachable
- Aggressive retries (15-second polling) accumulate failed requests
- This can cascade to affect Home Assistant's event loop responsiveness
- In severe cases, HA's web UI becomes unresponsive
Suggested Fix
Add retry logic specifically for RemoteProtocolError. Other Home Assistant integrations have implemented this:
- Philips TV integration: "We retry once, could be a reused session that was closed."
- Axis camera integration: Added retry on this specific error
Example approach:
from httpcore import RemoteProtocolError
async def fetch_with_retry(self, url, max_retries=1):
for attempt in range(max_retries + 1):
try:
return await self._client.get(url)
except RemoteProtocolError:
if attempt == max_retries:
raise
# Connection was closed server-side, retry with fresh connection
await self._client.aclose()
self._client = self._create_client()Alternatively, configure httpx to disable connection pooling or reduce keep-alive timeout:
limits = httpx.Limits(max_keepalive_connections=0)
client = httpx.AsyncClient(limits=limits)Environment
- Home Assistant version: 2025.12.4
- SPAN Panel integration version: latest from HACS
- SPAN Panel firmware: current
- Two SPAN panels configured with 15-second scan interval
References
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels