aio-libs/aiohttp · error · BadHttpMessage

Too many headers received

Error message

Too many headers received

What it means

Raised by HttpParser.feed_data (aiohttp/http_parser.py:384) when the number of accumulated lines (request/status line plus every header line) exceeds max_headers (default 128). This is a memory-exhaustion / DoS guard: it caps how many header lines a single message can carry before the parser refuses.

Source

Thrown at aiohttp/http_parser.py:384

                    continue

                if pos >= start_pos:
                    if should_close:
                        raise BadHttpMessage("Data after `Connection: close`")

                    # line found
                    line = data[start_pos:pos]
                    if SEP == b"\n":  # For lax response parsing
                        line = line.rstrip(b"\r")
                    if len(line) > max_line_length:
                        raise LineTooLong(line[:100] + b"...", max_line_length)

                    self._lines.append(line)
                    # After processing the status/request line, everything is a header.
                    max_line_length = self.max_field_size

                    if len(self._lines) > self.max_headers:
                        raise BadHttpMessage("Too many headers received")

                    start_pos = pos + len(SEP)

                    # \r\n\r\n found
                    if self._lines[-1] == EMPTY:
                        max_trailers = self.max_headers - len(self._lines)
                        try:
                            msg: _MsgT = self.parse_message(self._lines)
                        finally:
                            self._lines.clear()

                        def get_content_length() -> int | None:
                            # payload length
                            length_hdr = msg.headers.get(CONTENT_LENGTH)
                            if length_hdr is None:
                                return None

                            # Shouldn't allow +/- or other number formats.

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Raise max_headers (server: Application request-parser kwargs) for routes that legitimately need more.
  2. Reduce the number of headers your client sends; consolidate or drop redundant ones.
  3. On the server, the default 128 returns 400 - monitor and tune per route if needed; rate-limit clients that flood headers.

Example fix

# before - default max_headers (128) too low
app = web.Application()
# after - raise the cap for routes that need it
app = web.Application(handler_args={'max_headers': 256})
Defensive patterns

Strategy: validation

Validate before calling

MAX_OUTGOING_HEADERS = 128
def header_count_ok(headers) -> bool:
    return len(headers) <= MAX_OUTGOING_HEADERS
if not header_count_ok(outgoing):
    raise ValueError(f'too many headers ({len(outgoing)})')

Try / catch

from aiohttp import http_exceptions
try:
    await request.read()
except http_exceptions.BadHttpMessage as e:
    if 'Too many headers' in str(e):
        return web.Response(status=431)  # Request Header Fields Too Large
    raise

Prevention

When it happens

Trigger: A request or response carrying more than 128 header lines (the count includes the leading request/status line). Triggered by header-flood traffic or, rarely, by a legitimate API that attaches dozens of custom headers.

Common situations: DoS/header-flood attacks; crawlers or SDKs that attach many trace/debug headers; legitimate but unusual APIs that exceed 128 distinct headers; or a client loop that accidentally stacks headers.

Related errors


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