aio-libs/aiohttp · error · ClientConnectionResetError

Cannot write to closing transport

Error message

Cannot write to closing transport

What it means

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.

Source

Thrown at aiohttp/http_writer.py:103

        return self._protocol

    def enable_chunking(self) -> None:
        self.chunked = True

    def enable_compression(
        self, encoding: str = "deflate", strategy: int | None = None
    ) -> None:
        self._compress = ZLibCompressor(encoding=encoding, strategy=strategy)

    def _write(
        self, chunk: Union[bytes, bytearray, "memoryview[int]", "memoryview[bytes]"]
    ) -> None:
        size = len(chunk)
        self.buffer_size += size
        self.output_size += size
        transport = self._protocol.transport
        if transport is None or transport.is_closing():
            raise ClientConnectionResetError("Cannot write to closing transport")
        transport.write(chunk)

    def _writelines(
        self,
        chunks: Iterable[
            Union[bytes, bytearray, "memoryview[int]", "memoryview[bytes]"]
        ],
    ) -> None:
        size = 0
        for chunk in chunks:
            size += len(chunk)
        self.buffer_size += size
        self.output_size += size
        transport = self._protocol.transport
        if transport is None or transport.is_closing():
            raise ClientConnectionResetError("Cannot write to closing transport")
        if SKIP_WRITELINES or size < MIN_PAYLOAD_FOR_WRITELINES:
            transport.write(b"".join(chunks))

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Guard writes with try/except ClientConnectionResetError and stop gracefully.
  2. Avoid writing after the response/task is finished; check writer for EOF.
  3. Increase timeouts if the peer is slow but legitimate.
  4. Implement idempotent handlers so a retry can succeed.

Example fix

// before
#   await response.write(chunk)  # may raise after client disconnect

# after
from aiohttp import ClientConnectionResetError
try:
    await response.write(chunk)
except ClientConnectionResetError:
    # client gone — stop writing
    return
Defensive patterns

Strategy: try-catch

Validate before calling

def transport_writable(writer) -> bool:
    t = writer.transport
    return t is not None and not t.is_closing()

Try / catch

from aiohttp import ClientConnectionResetError
try:
    await stream_writer.write(data)
except ClientConnectionResetError:
    log.info('peer disconnected mid-write')
    return

Prevention

When it happens

Trigger: 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.

Common situations: Client disconnects before the response finishes; peer reset (RST); idle timeout closing the transport; writing after the handler returned; concurrent close from another task.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/98ba53ab7e144d7b.json. Report an issue: GitHub.