aio-libs/aiohttp · error · LineTooLong

Got more than bytes when reading: .

Error message

Got more than {limit} bytes when reading: {line!r}.

What it means

Raised (as LineTooLong, a BadHttpMessage subclass) by StreamReader.readuntil when the accumulated chunk before the separator exceeds max_size bytes. The default max_size is the reader's high-water mark (2 * read_buf_size). This protects against unbounded memory growth from a missing delimiter or an oversized line. The message reports the limit and a truncated prefix of the offending data.

Solutions

  1. Pass an explicit larger limit: await stream.readuntil(max_size=10 * 1024 * 1024).
  2. Increase the reader's buffer when constructing: StreamReader(..., read_buf_size=2**20).
  3. Switch to chunked reads (await stream.read(n)) instead of delimiter-based reads for binary/large data.

Example fix

# before
line = await stream.readuntil(b'\n')  # LineTooLong on big lines

# after
line = await stream.readuntil(b'\n', max_size=16 * 1024 * 1024)
Defensive patterns

Strategy: validation

Validate before calling

MAX = 16 * 1024 * 1024
line = await stream.readuntil(b'\n', max_size=MAX)

Type guard

def adequate_limit(stream, needed: int) -> bool:
    return stream._high_water >= needed

Try / catch

from aiohttp.http_exceptions import LineTooLong
try:
    line = await stream.readuntil(b'\n')
except LineTooLong:
    line = await stream.readuntil(b'\n', max_size=64 * 1024 * 1024)

Prevention

When it happens

Trigger: Calling await stream.readuntil() / readline() on a stream whose next delimiter is farther than max_size bytes away; a server sending a very long header line or a binary blob with no newline; default high-water mark too small for legitimate payloads.

Common situations: Reading MIME/multipart boundaries that exceed the default limit; large JSON-lines payloads; binary protocols mistaken for line-based; default read buffer size left at 2**16.

Related errors


AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11). Data as JSON: /api/errors/192ec574d4043d83. Report an issue: GitHub.

Appendix: source

Thrown at aiohttp/streams.py:410

        chunk_size = 0
        not_enough = True
        max_size = max_size or self._high_water

        while not_enough:
            while self._buffer and not_enough:
                offset = self._buffer_offset
                ichar = self._buffer[0].find(separator, offset) + 1
                # Read from current offset to found separator or to the end.
                data = self._read_nowait_chunk(
                    ichar - offset + seplen - 1 if ichar else -1
                )
                chunk += data
                chunk_size += len(data)
                if ichar:
                    not_enough = False

                if chunk_size > max_size:
                    raise LineTooLong(chunk[:100] + b"...", max_size)

            if self._eof:
                break

            if not_enough:
                await self._wait("readuntil")

        if chunk and self._on_chunk_received is not None:
            await self._fire_chunk_received(chunk)
        return chunk

    async def read(self, n: int = -1) -> bytes:
        if self._exception is not None:
            raise self._exception

        if not n:
            return b""

View on GitHub (pinned to d041d4d0fd)