microsoft/aspire · error · ConnectionError
Connection closed
Error message
Connection closed
What it means
Raised by _recv_exactly in the generated Python client when the underlying pipe/socket returns an empty chunk before the requested number of bytes has been read. An empty recv means the peer closed the connection, so a complete message can no longer be assembled.
Solutions
- Catch ConnectionError and re-establish the connection before retrying the operation.
- Verify the host process was alive for the duration of the call; inspect host logs for crashes.
- Reduce the chance of mid-response disconnects by keeping requests within host-side deadlines.
- Treat any in-flight partial message as discarded after reconnect (the protocol has no resume).
Example fix
// before
response = client.invoke_capability("get_items", args)
// after
try:
response = client.invoke_capability("get_items", args)
except ConnectionError:
client.reconnect()
response = client.invoke_capability("get_items", args) Defensive patterns
Strategy: try-catch
Try / catch
try:
response = client.invoke_capability(cap, args)
except ConnectionError:
client.reconnect()
response = client.invoke_capability(cap, args) Prevention
- Keep the host alive for the whole client session.
- Reconnect after any error instead of reusing a suspect stream.
- Monitor host logs for crashes correlating with disconnects.
When it happens
Trigger: Calling any client method that reads a length-prefixed response after the host has closed or exited; host restarting between request and response; abrupt process kill mid-response.
Common situations: AppHost stopped while the client holds an idle connection; host crash mid-request; timeout/kill on the server side for a long-running capability.
Understand the failure class
- Connection failures: ECONNREFUSED, ECONNRESET, and friends — why connections get refused, reset, or dropped.
Related errors
- Headers too large (limit bytes)
- Message too large: bytes (limit bytes)
- Too many headers (limit )
- A ConfigureRadiusInfrastructure callback replaced the…
- Array params contains empty item
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/0a0d98d3ad763b88.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.CodeGeneration.Python/PythonModuleBuilder.cs:906
signal.signal(signal.SIGINT, self._handle_sigint)
_logger.info("Connected to AppHost")
# Start receiving messages in a background thread
self._receive_thread = threading.Thread(target=self._receive_loop, daemon=True)
self._receive_thread.start()
# Start heartbeat thread to monitor connection health
self._heartbeat_thread = threading.Thread(target=self._heartbeat_loop, daemon=True)
self._heartbeat_thread.start()
def _recv_exactly(self, n: int) -> bytes:
'''Read exactly n bytes from the socket'''
data = b""
while len(data) < n:
chunk = typing.cast(_PipeSocket, self._socket).recv(n - len(data))
if not chunk:
raise ConnectionError("Connection closed")
data += chunk
return data
def _read_line(self) -> bytes:
'''Read a line ending with \\r\\n from the socket'''
line = b""
while True:
byte = typing.cast(_PipeSocket, self._socket).recv(1)
if not byte:
raise ConnectionError("Connection closed")
line += byte
if line.endswith(b"\r\n"):
return line[:-2] # Remove \r\n
def _read_headers(self) -> dict[str, str]:
'''Read HTTP-style headers until empty line.
Enforces limits on header count and total size to preventView on GitHub (pinned to 25830f84bd)