aio-libs/aiohttp · error · BadHttpMethod

Bad HTTP method in status line

Error message

Bad HTTP method in status line {method!r}

What it means

Raised when the method token does not fully match TOKENRE [0-9A-Za-z!#$%&'*+-.^_`|~]+. Methods must be RFC 9110 tokens: no spaces, no control bytes, no delimiters.

Solutions

  1. Send a standard method token (GET, POST, ...).
  2. Validate custom methods against the token charset before sending.
  3. Reject malformed methods at the edge.

Example fix

# before
sock.send(b'G@T / HTTP/1.1\r\n')

# after
sock.send(b'GET / HTTP/1.1\r\n')
Defensive patterns

Strategy: validation

Validate before calling

import re
_TOKEN = re.compile(r"[0-9A-Za-z!#$%&'*+-.^_`|~]+")
def safe_method(m: str) -> str | None:
    return m if _TOKEN.fullmatch(m) else None

Type guard

import re
_TOKEN = re.compile(r"[0-9A-Za-z!#$%&'*+-.^_`|~]+")
def is_method_token(m: str) -> bool:
    return bool(_TOKEN.fullmatch(m))

Try / catch

from aiohttp.http_exceptions import BadHttpMethod
try:
    ...parse...
except BadHttpMethod as e:
    transport.close()

Prevention

When it happens

Trigger: A method containing any non-token character: 'GE/T', 'GET\r' (CRLF injection), an empty method, or a custom method with delimiters.

Common situations: Custom clients sending malformed methods, CRLF-injection attacks, fuzzing, encoding bugs.

Related errors


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

Appendix: source

Thrown at aiohttp/http_parser.py:665

class HttpRequestParser(HttpParser[RawRequestMessage]):
    """Read request status line.

    Exception .http_exceptions.BadStatusLine
    could be raised in case of any errors in status line.
    Returns RawRequestMessage.
    """

    def parse_message(self, lines: list[bytes]) -> RawRequestMessage:
        # request line
        line = lines[0].decode("utf-8", "surrogateescape")
        try:
            method, path, version = line.split(" ", maxsplit=2)
        except ValueError:
            raise BadHttpMethod(line) from None

        # method
        if not TOKENRE.fullmatch(method):
            raise BadHttpMethod(method)
        method = method.upper()

        # version
        match = VERSRE.fullmatch(version)
        if match is None:
            raise BadStatusLine(line)
        version_o = HttpVersion(int(match.group(1)), int(match.group(2)))

        if method == "CONNECT":
            # authority-form,
            # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3
            url = URL.build(authority=path, encoded=True)
        elif path.startswith("/"):
            # origin-form,
            # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1
            path_part, _hash_separator, url_fragment = path.partition("#")
            path_part, _question_mark_separator, qs_part = path_part.partition("?")

View on GitHub (pinned to d041d4d0fd)