{"record":{"id":"4d72e200bc582d7f","repo":"aio-libs/aiohttp","slug":"request-has-duplicate-chunked-transfer-encoding","errorCode":null,"errorMessage":"Request has duplicate `chunked` Transfer-Encoding","messagePattern":"Request has duplicate `chunked` Transfer-Encoding","errorType":"exception","errorClass":"BadHttpMessage","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":747,"sourceCode":"            path,\n            version_o,\n            headers,\n            raw_headers,\n            close,\n            compression,\n            upgrade,\n            chunked,\n            url,\n        )\n\n    def _is_chunked_te(self, te: str) -> bool:\n        # https://www.rfc-editor.org/rfc/rfc9112#section-7.1-3\n        # \"A sender MUST NOT apply the chunked transfer coding more\n        #  than once to a message body\"\n        parts = [p.strip(\" \\t\") for p in te.split(\",\")]\n        chunked_count = sum(1 for p in parts if p.isascii() and p.lower() == \"chunked\")\n        if chunked_count > 1:\n            raise BadHttpMessage(\"Request has duplicate `chunked` Transfer-Encoding\")\n        last = parts[-1]\n        # .lower() transforms some non-ascii chars, so must check first.\n        if last.isascii() and last.lower() == \"chunked\":\n            return True\n        # https://www.rfc-editor.org/rfc/rfc9112#section-6.3-2.4.3\n        raise BadHttpMessage(\"Request has invalid `Transfer-Encoding`\")\n\n\nclass HttpResponseParser(HttpParser[RawResponseMessage]):\n    \"\"\"Read response status line and headers.\n\n    BadStatusLine could be raised in case of any errors in status line.\n    Returns RawResponseMessage.\n    \"\"\"\n\n    protocol: \"ResponseHandler\"\n\n    # Lax mode should only be enabled on response parser.","sourceCodeStart":729,"sourceCodeEnd":765,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/http_parser.py#L729-L765","documentation":"Raised as BadHttpMessage (HTTP 400) when the Transfer-Encoding header contains the 'chunked' coding more than once. RFC 9112 §7.1 forbids applying the chunked transfer coding more than once to a message body. The guard lives in HttpRequestParser._is_chunked_te: it splits TE on commas and counts case-insensitive ASCII 'chunked' tokens; more than one raises.","triggerScenarios":"A request with 'Transfer-Encoding: chunked, chunked' (or any comma-separated list containing 'chunked' twice). Parsed by _is_chunked_te before the body is read; triggered during parse_headers when the TE header is present.","commonSituations":"A buggy intermediary (proxy, middleware) that appends 'chunked' to an already-chunked TE header; fuzzing/security scanners probing encoding-handling bugs; misconfigured reverse proxy double-encoding chunked transfers; an HTTP/1.1 client built manually that stacks the encoding.","solutions":["Send Transfer-Encoding with at most one 'chunked' token (it must be the last token if present).","Fix the proxy/middleware that is appending 'chunked' a second time to the TE header.","If you control the client, ensure the TE header is built once and not concatenated across hops.","Validate outgoing TE headers before sending: a single trailing 'chunked' only."],"exampleFix":"// before\r\nTransfer-Encoding: chunked, chunked\\r\\n\r\n\r\n// after\r\nTransfer-Encoding: chunked\\r\\n","handlingStrategy":"validation","validationCode":"def normalize_transfer_encoding(te: str) -> str:\n    parts = [p.strip(\" \\t\") for p in te.split(',')]\n    chunked_count = sum(1 for p in parts if p.isascii() and p.lower() == 'chunked')\n    if chunked_count > 1:\n        # collapse duplicates: keep a single trailing 'chunked'\n        parts = [p for p in parts if not (p.isascii() and p.lower() == 'chunked')]\n        parts.append('chunked')\n    return ','.join(parts)","typeGuard":null,"tryCatchPattern":"from aiohttp.http_exceptions import BadHttpMessage\n\ntry:\n    parser.feed_data(raw)\nexcept BadHttpMessage as e:\n    respond_400(str(e))  # duplicate chunked / invalid TE","preventionTips":["Never append 'chunked' to TE without checking it is not already present.","Build TE once at the origin and do not let intermediaries re-add codings.","Validate TE headers in test fixtures: at most one trailing 'chunked'."],"tags":["http-parser","transfer-encoding","chunked","rfc-9112","security"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}