aio-libs/aiohttp · error · ValueError

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

Error message

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

What it means

Raised by ClientRequest._update_transfer_encoding() when the request both has a 'Transfer-Encoding: chunked' header already and the internal chunked flag is True. The two represent the same encoding, so providing both is contradictory and aiohttp raises ValueError. The check inspects the lower-cased Transfer-Encoding header for the substring 'chunked'.

Solutions

  1. Don't set Transfer-Encoding manually; let aiohttp manage chunked encoding based on the body type.
  2. If you set the header yourself, ensure chunked mode isn't also triggered (avoid compress and streaming generators simultaneously).
  3. Prefer setting Content-Length for fixed-size bodies to avoid chunked entirely.
  4. Remove any manual 'Transfer-Encoding' header before passing a streaming body.

Example fix

# before
headers['Transfer-Encoding'] = 'chunked'
await session.post(url, data=stream_gen, headers=headers)  # ValueError

# after — let aiohttp decide; remove manual header
await session.post(url, data=stream_gen)
Defensive patterns

Strategy: validation

Validate before calling

def clean_headers_for_chunked(headers, chunked):
    te = headers.get('Transfer-Encoding', '').lower()
    if 'chunked' in te and chunked:
        # let aiohttp own chunked encoding
        headers.pop('Transfer-Encoding', None)
    return headers

Type guard

def transfer_encoding_is_unambiguous(headers, chunked) -> bool:
    te = headers.get('Transfer-Encoding', '').lower()
    return not ('chunked' in te and chunked)

Try / catch

try:
    await session.post(url, data=stream, headers=headers)
except ValueError as e:
    if 'Transfer-Encoding' in str(e):
        headers = {k:v for k,v in headers.items() if k.lower() != 'transfer-encoding'}
        await session.post(url, data=stream, headers=headers)
    else:
        raise

Prevention

When it happens

Trigger: Setting headers['Transfer-Encoding']='chunked' manually AND triggering chunked mode (e.g. via compress, or chunked=True through internal logic, or passing a streaming body). _update_transfer_encoding sees 'chunked' in the header plus self.chunked True and raises ValueError.

Common situations: Manually adding a Transfer-Encoding header while also using a generator/stream body that auto-enables chunking; mixing explicit headers with the high-level chunked/compress APIs; copy-paste from a raw HTTP example.

Related errors


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

Appendix: 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 d041d4d0fd)