aio-libs/aiohttp · error · ValueError

chunked can not be set if "Transfer-Encoding: chunked" heade

Error message

chunked can not be set if "Transfer-Encoding: chunked" header is set

What it means

Raised as ValueError in _update_transfer_encoding() when the request already has a 'Transfer-Encoding: chunked' header AND self.chunked is True. Setting chunked twice (via the flag and via the header) is contradictory, so aiohttp rejects it to avoid ambiguous framing.

Source

Thrown at aiohttp/client_reqrep.py:1228

                raise ValueError(
                    "compress can not be set if Content-Encoding header is set"
                )
        elif compress:
            if isinstance(compress, str) and compress not in {"deflate", "gzip"}:
                raise ValueError(
                    "compress must be one of True, False, 'deflate', or 'gzip'"
                )
            self.compress = compress if isinstance(compress, str) else "deflate"
            self.headers[hdrs.CONTENT_ENCODING] = self.compress
            self.chunked = True  # enable chunked, no need to deal with length

    def _update_transfer_encoding(self) -> None:
        """Analyze transfer-encoding header."""
        te = self.headers.get(hdrs.TRANSFER_ENCODING, "").lower()

        if "chunked" in te:
            if self.chunked:
                raise ValueError(
                    "chunked can not be set "
                    'if "Transfer-Encoding: chunked" header is set'
                )

        elif self.chunked:
            if hdrs.CONTENT_LENGTH in self.headers:
                raise ValueError(
                    "chunked can not be set if Content-Length header is set"
                )

            self.headers[hdrs.TRANSFER_ENCODING] = "chunked"

    def _update_body_from_data(self, body: Any) -> None:
        """Update request body from data."""
        if body is None:
            self._body = self._EMPTY_BODY
            # Set Content-Length to 0 when body is None for methods that expect a body
            if (

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Use only one mechanism: either set the Transfer-Encoding header manually OR pass chunked=True, not both.
  2. If you set Transfer-Encoding: chunked yourself, leave chunked at its default (False).
  3. Remove the manual header when using the chunked flag.

Example fix

# before
await session.post(url, data=stream, chunked=True,
                  headers={'Transfer-Encoding': 'chunked'})
# after
await session.post(url, data=stream, chunked=True)
# or
await session.post(url, data=stream,
                  headers={'Transfer-Encoding': 'chunked'})
Defensive patterns

Strategy: validation

Validate before calling

te = headers.get('Transfer-Encoding', '').lower()
if chunked and 'chunked' in te:
    chunked = False  # header already conveys intent

Prevention

When it happens

Trigger: Fires at line 1226-1231 when 'chunked' is in the lowercase Transfer-Encoding header and self.chunked (the flag) is True. Triggered by passing both chunked=True and headers={'Transfer-Encoding': 'chunked'} to the request.

Common situations: Combining manual Transfer-Encoding header with the chunked convenience flag; copying headers verbatim from curl commands while also passing chunked=True.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/f2285e50c7c3439a.json. Report an issue: GitHub.