{"record":{"id":"4787f5a133a8711f","repo":"aio-libs/aiohttp","slug":"connection-closed-4787f5","errorCode":null,"errorMessage":"Connection closed.","messagePattern":"Connection closed\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/streams.py","lineNumber":351,"sourceCode":"            return\n\n        self._http_chunk_splits.append(self.total_bytes)\n\n        # If we get too many small chunks before self._high_water is reached, then any\n        # .read() call becomes computationally expensive, and could block the event loop\n        # for too long, hence an additional self._high_water_chunks here.\n        if len(self._http_chunk_splits) > self._high_water_chunks:\n            self._protocol.pause_reading()\n\n        # wake up readchunk when end of http chunk received\n        waiter = self._waiter\n        if waiter is not None:\n            self._waiter = None\n            set_result(waiter, None)\n\n    async def _wait(self, func_name: str) -> None:\n        if not self._protocol.connected:\n            raise RuntimeError(\"Connection closed.\")\n\n        # StreamReader uses a future to link the protocol feed_data() method\n        # to a read coroutine. Running two read coroutines at the same time\n        # would have an unexpected behaviour. It would not possible to know\n        # which coroutine would get the next data.\n        if self._waiter is not None:\n            raise RuntimeError(\n                \"%s() called while another coroutine is \"\n                \"already waiting for incoming data\" % func_name\n            )\n\n        waiter = self._waiter = self._loop.create_future()\n        try:\n            with self._timer:\n                await waiter\n        finally:\n            self._waiter = None\n","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/streams.py#L333-L369","documentation":"Raised by StreamReader._wait when self._protocol.connected is False at the moment a read coroutine is about to await new data. It means the underlying transport/protocol has disconnected, so blocking for more data would hang forever; aiohttp raises instead. This typically surfaces wrapped in a ClientPayloadError or ServerDisconnectedError depending on context.","triggerScenarios":"Calling await response.content.read(n), readline(), or readuntil() after the server closed the connection (or after the response body was already fully consumed and the protocol detached); reading a request body on the server side after the client disconnected.","commonSituations":"Server closed keep-alive connection between reads; reading past Content-Length; proxy/load-balancer dropping an idle connection; client disconnect during server-side request body streaming.","solutions":["Treat a fully-read response as done: check response.content.at_eof() before reading more.","Catch the error (often as aiohttp.ClientPayloadError or ServerDisconnectedError) and retry the request or close cleanly.","Ensure you read the body exactly once and within the response context manager."],"exampleFix":"# before\ndata = await response.content.read(1024)  # may raise after disconnect\n\n# after\nif not response.content.at_eof():\n    data = await response.content.read(1024)\nelse:\n    data = b''","handlingStrategy":"validation","validationCode":"if response.content.at_eof() or not response.content._protocol.connected:\n    data = b''\nelse:\n    data = await response.content.read(n)","typeGuard":"def stream_readable(stream) -> bool:\n    return getattr(stream, '_protocol', None) is not None and stream._protocol.connected and not stream.at_eof()","tryCatchPattern":"try:\n    data = await response.content.read(n)\nexcept (RuntimeError, aiohttp.ClientPayloadError, aiohttp.ServerDisconnectedError):\n    data = b''  # connection gone; handle partial/no data","preventionTips":["Always read response bodies within the async with response context.","Check at_eof() before requesting more data in a loop.","Handle ClientPayloadError to tolerate mid-stream disconnects."],"tags":["streams","connection","lifecycle","network"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}