aio-libs/aiohttp · error · InvalidHeader
Invalid HTTP header: {hdr!r}
Error message
Invalid HTTP header: {hdr!r} What it means
Raised by HeadersParser.parse_headers as InvalidHeader (a BadHttpMessage subclass, HTTP 400) when a header line cannot be split into name:value on a colon — i.e. line.split(b':', 1) returns a single element, meaning the line has no colon at all. This is a malformed request/response header line.
Source
Thrown at aiohttp/http_parser.py:181
def __init__(self, max_field_size: int = 8190, lax: bool = False) -> None:
self.max_field_size = max_field_size
self._lax = lax
def parse_headers(self, lines: list[bytes]) -> tuple[HeadersDictProxy, RawHeaders]:
headers: CIMultiDict[str] = CIMultiDict()
# note: "raw" does not mean inclusion of OWS before/after the field value
raw_headers = []
lines_idx = 0
line = lines[lines_idx]
line_count = len(lines)
while line:
# Parse initial header name : value pair.
try:
bname, bvalue = line.split(b":", 1)
except ValueError:
raise InvalidHeader(line) from None
if len(bname) == 0:
raise InvalidHeader(bname)
# https://www.rfc-editor.org/rfc/rfc9112.html#section-5.1-2
if {bname[0], bname[-1]} & {32, 9}: # {" ", "\t"}
raise InvalidHeader(line)
bvalue = bvalue.lstrip(b" \t")
name = bname.decode("utf-8", "surrogateescape")
if not TOKENRE.fullmatch(name):
raise InvalidHeader(bname)
# next line
lines_idx += 1
line = lines[lines_idx]
# consume continuation linesView on GitHub (pinned to c0ef574e29)
Solutions
- If you control the peer, fix it to emit 'Name: Value' lines.
- Increase robustness on the client side by catching aiohttp.ClientResponseError / BadHttpMessage.
- Inspect the raw response with a lower-level tool to find the offending header.
Example fix
// before # peer sends: Accept-Encoding gzip (no colon) // after # peer sends: Accept-Encoding: gzip
Defensive patterns
Strategy: try-catch
Validate before calling
def header_has_colon(line: bytes) -> bool:
return b':' in line Try / catch
from aiohttp.http_exceptions import InvalidHeader
try:
headers, raw = parser.parse_headers(lines)
except InvalidHeader as e:
log.warning('peer sent malformed header: %r', e.hdr) Prevention
- If you produce headers, always emit 'Name: Value' with a colon.
- On the client side, catch ClientResponseError/InvalidHeader for malformed servers.
- Inspect raw bytes with curl -i to locate the offending header.
When it happens
Trigger: A peer (server or client) sending a header line like b'Accept-Encoding gzip' (space instead of colon), or a bare token line with no colon. The parser is fed raw header lines split on CRLF.
Common situations: Malformed upstream responses; hand-rolled HTTP clients/servers emitting bad headers; proxies rewriting headers incorrectly; binary garbage interpreted as headers.
Related errors
- Invalid upgrade header
- Invalid Content-Length header: {content_length_hdr!r}
- compress can not be set if Content-Encoding header is set
- chunked can not be set if "Transfer-Encoding: chunked" heade
- chunked can not be set if Content-Length header is set
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/1fa9ec9c82669274.json.
Report an issue: GitHub.