{"id":"a71b654e08536454","repo":"aio-libs/aiohttp","slug":"bad-status-line-line-r","errorCode":null,"errorMessage":"Bad status line {line!r}","messagePattern":"Bad status line (.+?)","errorType":"http","errorClass":"BadStatusLine","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":669,"sourceCode":"    \"\"\"\n\n    def parse_message(self, lines: list[bytes]) -> RawRequestMessage:\n        # request line\n        line = lines[0].decode(\"utf-8\", \"surrogateescape\")\n        try:\n            method, path, version = line.split(\" \", maxsplit=2)\n        except ValueError:\n            raise BadHttpMethod(line) from None\n\n        # method\n        if not TOKENRE.fullmatch(method):\n            raise BadHttpMethod(method)\n        method = method.upper()\n\n        # version\n        match = VERSRE.fullmatch(version)\n        if match is None:\n            raise BadStatusLine(line)\n        version_o = HttpVersion(int(match.group(1)), int(match.group(2)))\n\n        if method == \"CONNECT\":\n            # authority-form,\n            # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.3\n            url = URL.build(authority=path, encoded=True)\n        elif path.startswith(\"/\"):\n            # origin-form,\n            # https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.1\n            path_part, _hash_separator, url_fragment = path.partition(\"#\")\n            path_part, _question_mark_separator, qs_part = path_part.partition(\"?\")\n\n            # NOTE: `yarl.URL.build()` is used to mimic what the Cython-based\n            # NOTE: parser does, otherwise it results into the same\n            # NOTE: HTTP Request-Line input producing different\n            # NOTE: `yarl.URL()` objects\n            url = URL.build(\n                path=path_part,","sourceCodeStart":651,"sourceCodeEnd":687,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/http_parser.py#L651-L687","documentation":"Raised by HttpRequestParser.parse_message (aiohttp/http_parser.py:669) when the version token (third element of the request line) does not fullmatch VERSRE (HTTP/(\\d)\\.(\\d)). Caught forms include missing 'HTTP/' prefix ('1.1'), missing minor version ('HTTP/2'), wrong prefix ('FOO/1.1'), or garbage. Note 'HTTP/2.0' DOES match and yields HttpVersion(2,0); 'HTTP/3' does NOT (no dot).","triggerScenarios":"A request line like 'GET / 1.1' (no HTTP/), 'GET / HTTP/2' (no minor), 'GET / FOO/1.1', or 'GET / HTTP/1.1 ' (trailing space - though split would keep it in the version token). Fires whenever the version token fails the strict HTTP/x.y pattern.","commonSituations":"Raw socket clients omitting the version, non-HTTP protocols reusing the parser, hand-built requests with typos, or HTTP/2-only clients that send a non-standard preface on an HTTP/1.1 connection.","solutions":["Include a well-formed version token ('HTTP/1.1' or 'HTTP/1.0') as the third space-separated element.","Use a real HTTP client that formats the request line correctly.","If supporting HTTP/2, ensure the client negotiates via ALPN rather than sending a custom request line."],"exampleFix":"# before - missing/wrong version token\nsock.send(b'GET / 1.1\\r\\n\\r\\n')        # no 'HTTP/' prefix\nsock.send(b'GET / HTTP/2\\r\\n\\r\\n')     # no minor version\n# after\nsock.send(b'GET / HTTP/1.1\\r\\nHost: x\\r\\n\\r\\n')","handlingStrategy":"validation","validationCode":"import re\n_VERSRE = re.compile(r'HTTP/(\\d)\\.(\\d)\\Z')\ndef valid_http_version(token: str) -> bool:\n    m = _VERSRE.fullmatch(token)\n    if not m:\n        return False\n    return tuple(int(x) for x in m.groups()) in {(1,0),(1,1),(2,0)}\nassert valid_http_version(version_token)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include a well-formed HTTP/x.y version token in the request line","Use an HTTP library that formats the request line","Negotiate HTTP/2 via ALPN, not by editing the request line"],"tags":["http","protocol","parser","request-line","version"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}