{"record":{"id":"cf31f2735c6a95d7","repo":"aio-libs/aiohttp","slug":"request-has-invalid-transfer-encoding","errorCode":null,"errorMessage":"Request has invalid `Transfer-Encoding`","messagePattern":"Request has invalid `Transfer-Encoding`","errorType":"exception","errorClass":"BadHttpMessage","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":753,"sourceCode":"            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.\n    lax = not DEBUG\n\n    def feed_data(\n        self,\n        data: bytes,\n        SEP: _SEP | None = None,","sourceCodeStart":735,"sourceCodeEnd":771,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/http_parser.py#L735-L771","documentation":"Raised as BadHttpMessage (HTTP 400) when a Transfer-Encoding header is present and its last comma-separated token is not 'chunked'. RFC 9112 §6.3 requires that, when chunked is used, it must be the final transfer coding. The guard in _is_chunked_te returns True only if the last token (ASCII, case-insensitive) equals 'chunked'; otherwise it raises this error.","triggerScenarios":"A request with a Transfer-Encoding whose last token is something other than 'chunked' (e.g. 'gzip', 'identity', or an unknown coding), or where 'chunked' appears but is not last. Fires inside _is_chunked_te when the TE header is non-empty and does not end in chunked.","commonSituations":"Client/intermediary sends 'Transfer-Encoding: gzip' (non-standard, should use Content-Encoding); a custom coding name with a typo; a server/old client using deprecated encodings; a proxy reordering TE tokens so chunked is not last; fuzzers probing the parser.","solutions":["Ensure the Transfer-Encoding header, when present, ends with 'chunked' as its last token.","Use Content-Encoding (not Transfer-Encoding) for gzip/deflate/br body compression.","Remove the Transfer-Encoding header entirely if you want a fixed-length body and send Content-Length instead.","Audit intermediaries that rewrite TE to make sure they preserve chunked-last ordering."],"exampleFix":"// before (non-chunked last token)\r\nTransfer-Encoding: gzip\\r\\n\r\n\r\n// after (use Content-Encoding for compression)\r\nContent-Encoding: gzip\\r\\nContent-Length: 123\\r\\n\r\n\r\n// or, if chunked streaming is intended, chunked must be last\r\nTransfer-Encoding: gzip, chunked\\r\n","handlingStrategy":"validation","validationCode":"def is_valid_te(te: str) -> bool:\n    parts = [p.strip(\" \\t\") for p in te.split(',')]\n    last = parts[-1]\n    return last.isascii() and last.lower() == 'chunked'\n\n# use Content-Encoding for compression, not a non-chunked Transfer-Encoding","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))","preventionTips":["Use Content-Encoding (not Transfer-Encoding) for body compression.","Ensure 'chunked', when used, is the last TE token.","Drop TE entirely in favor of Content-Length for fixed-length bodies."],"tags":["http-parser","transfer-encoding","chunked","rfc-9112"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}