aio-libs/aiohttp · error · ValueError

compress can not be set if Content-Encoding header is set

Error message

compress can not be set if Content-Encoding header is set

What it means

Raised by ClientRequest._update_content_encoding() when a request supplies both a manually-set Content-Encoding header and a truthy 'compress' parameter. These are mutually exclusive ways to request body compression, so aiohttp refuses the ambiguous combination with ValueError. The method resets self.compress and, if data is present and Content-Encoding is set, any compress!=False triggers the error.

Solutions

  1. Choose one strategy: either pass compress=True/ 'gzip' and let aiohttp handle it, OR pre-compress the body and set Content-Encoding yourself (with compress=False).
  2. If you pre-compressed, drop compress or set compress=False.
  3. If you want aiohttp to compress, remove the manual Content-Encoding header.
  4. Verify data is non-empty; with no data the method returns early and compression is skipped.

Example fix

# before
await session.post(url, data=gzipped_body,
    headers={'Content-Encoding': 'gzip'}, compress=True)  # ValueError

# after — let aiohttp compress (recommended)
await session.post(url, data=raw_body, compress='gzip')
# or pre-compress yourself and don't pass compress
await session.post(url, data=gzipped_body, headers={'Content-Encoding': 'gzip'})
Defensive patterns

Strategy: validation

Validate before calling

def prepare_compression(headers, data, compress):
    # mutually exclusive: manual Content-Encoding vs compress param
    if headers.get('Content-Encoding') and compress:
        # pick one strategy
        headers.pop('Content-Encoding')  # let aiohttp compress
    return compress

Type guard

def compression_is_unambiguous(headers, compress) -> bool:
    return not (headers.get('Content-Encoding') and compress)

Try / catch

try:
    await session.post(url, data=body, headers=headers, compress=compress)
except ValueError as e:
    if 'Content-Encoding header is set' in str(e):
        headers.pop('Content-Encoding', None)
        await session.post(url, data=body, headers=headers, compress=compress)
    else:
        raise

Prevention

When it happens

Trigger: Calling session.post(url, data=body, headers={'Content-Encoding':'gzip'}, compress=True) — or compress='gzip'. _update_content_encoding sees the existing header plus a truthy compress and raises ValueError.

Common situations: Pre-compressing the body and setting the header, but also passing compress=True; copy-paste mixing two compression strategies; migrating code that manually gzipped payloads to the compress parameter without removing the header.

Related errors


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

Appendix: source

Thrown at aiohttp/client_reqrep.py:1210

            del self.headers[hdrs.COOKIE]

        for name, value in cookies.items():
            # Use helper to preserve coded_value exactly as sent by server
            c[name] = preserve_morsel_with_coded_value(value)

        self.headers[hdrs.COOKIE] = c.output(header="", sep=";").strip()

    def _update_content_encoding(
        self, data: Any, compress: bool | Literal["deflate", "gzip"]
    ) -> None:
        """Set request content encoding."""
        self.compress = None
        if not data:
            return

        if self.headers.get(hdrs.CONTENT_ENCODING):
            if compress:
                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(

View on GitHub (pinned to d041d4d0fd)