{"id":"98ba53ab7e144d7b","repo":"aio-libs/aiohttp","slug":"cannot-write-to-closing-transport-98ba53","errorCode":null,"errorMessage":"Cannot write to closing transport","messagePattern":"Cannot write to closing transport","errorType":"exception","errorClass":"ClientConnectionResetError","httpStatus":null,"severity":"error","filePath":"aiohttp/http_writer.py","lineNumber":103,"sourceCode":"        return self._protocol\n\n    def enable_chunking(self) -> None:\n        self.chunked = True\n\n    def enable_compression(\n        self, encoding: str = \"deflate\", strategy: int | None = None\n    ) -> None:\n        self._compress = ZLibCompressor(encoding=encoding, strategy=strategy)\n\n    def _write(\n        self, chunk: Union[bytes, bytearray, \"memoryview[int]\", \"memoryview[bytes]\"]\n    ) -> None:\n        size = len(chunk)\n        self.buffer_size += size\n        self.output_size += size\n        transport = self._protocol.transport\n        if transport is None or transport.is_closing():\n            raise ClientConnectionResetError(\"Cannot write to closing transport\")\n        transport.write(chunk)\n\n    def _writelines(\n        self,\n        chunks: Iterable[\n            Union[bytes, bytearray, \"memoryview[int]\", \"memoryview[bytes]\"]\n        ],\n    ) -> None:\n        size = 0\n        for chunk in chunks:\n            size += len(chunk)\n        self.buffer_size += size\n        self.output_size += size\n        transport = self._protocol.transport\n        if transport is None or transport.is_closing():\n            raise ClientConnectionResetError(\"Cannot write to closing transport\")\n        if SKIP_WRITELINES or size < MIN_PAYLOAD_FOR_WRITELINES:\n            transport.write(b\"\".join(chunks))","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/http_writer.py#L85-L121","documentation":"ClientConnectionResetError('Cannot write to closing transport') raised by StreamWriter._write when the underlying transport is None or already closing. The writer tried to push a chunk after the connection began shutting down.","triggerScenarios":"During response writing (server) or request body upload (client), _write checks `transport is None or transport.is_closing()` and raises when the peer has closed/reset the connection mid-flight. Surfaces from write()/write_eof() paths that call _write.","commonSituations":"Client disconnects before the response finishes; peer reset (RST); idle timeout closing the transport; writing after the handler returned; concurrent close from another task.","solutions":["Guard writes with try/except ClientConnectionResetError and stop gracefully.","Avoid writing after the response/task is finished; check writer for EOF.","Increase timeouts if the peer is slow but legitimate.","Implement idempotent handlers so a retry can succeed."],"exampleFix":"// before\n#   await response.write(chunk)  # may raise after client disconnect\n\n# after\nfrom aiohttp import ClientConnectionResetError\ntry:\n    await response.write(chunk)\nexcept ClientConnectionResetError:\n    # client gone — stop writing\n    return","handlingStrategy":"try-catch","validationCode":"def transport_writable(writer) -> bool:\n    t = writer.transport\n    return t is not None and not t.is_closing()","typeGuard":null,"tryCatchPattern":"from aiohttp import ClientConnectionResetError\ntry:\n    await stream_writer.write(data)\nexcept ClientConnectionResetError:\n    log.info('peer disconnected mid-write')\n    return","preventionTips":["Treat client disconnects as normal for long responses.","Don't keep writing once write_eof or connection close is signalled."],"tags":["http","writer","transport","connection-reset","network"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}