aio-libs/aiohttp · error · RuntimeError

unknown content transfer encoding: {te_encoding}

Error message

unknown content transfer encoding: {te_encoding}

What it means

Raised by MultipartWriter.append_payload() (non-form-data path) when a part's Content-Transfer-Encoding header is not one of base64, quoted-printable, or binary (empty is also allowed). The writer only implements those transfer encodings, so unrecognized values are rejected.

Source

Thrown at aiohttp/multipart.py:1036

                not {CONTENT_ENCODING, CONTENT_LENGTH, CONTENT_TRANSFER_ENCODING}
                & payload.headers.keys()
            )
            # Set default Content-Disposition in case user doesn't create one
            if CONTENT_DISPOSITION not in payload.headers:
                name = f"section-{len(self._parts)}"
                payload.set_content_disposition("form-data", name=name)
        else:
            # compression
            encoding = payload.headers.get(CONTENT_ENCODING, "").lower()
            if encoding and encoding not in ("deflate", "gzip", "identity"):
                raise RuntimeError(f"unknown content encoding: {encoding}")
            if encoding == "identity":
                encoding = None

            # te encoding
            te_encoding = payload.headers.get(CONTENT_TRANSFER_ENCODING, "").lower()
            if te_encoding not in ("", "base64", "quoted-printable", "binary"):
                raise RuntimeError(f"unknown content transfer encoding: {te_encoding}")
            if te_encoding == "binary":
                te_encoding = None

            # size
            size = payload.size
            if size is not None and not (encoding or te_encoding):
                payload.headers[CONTENT_LENGTH] = str(size)

        self._parts.append((payload, encoding, te_encoding))  # type: ignore[arg-type]
        return payload

    def append_json(
        self, obj: Any, headers: Mapping[str, str] | None = None
    ) -> Payload:
        """Helper to append JSON part."""
        if headers is None:
            headers = CIMultiDict()

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Use only 'base64', 'quoted-printable', or 'binary' (or remove the header) for non-form-data parts.
  2. For 7bit/8bit content, drop the header (treat as binary) since HTTP does not require transfer encoding.
  3. For form-data, never set Content-Transfer-Encoding at all.

Example fix

// before
payload.headers['Content-Transfer-Encoding'] = '8bit'
writer.append_payload(payload)  # -> RuntimeError
// after
del payload.headers['Content-Transfer-Encoding']
writer.append_payload(payload)
Defensive patterns

Strategy: validation

Validate before calling

cte = payload.headers.get('Content-Transfer-Encoding', '').lower()
if cte and cte not in ('base64', 'quoted-printable', 'binary'):
    del payload.headers['Content-Transfer-Encoding']

Type guard

def is_writer_supported_cte(payload) -> bool:
    cte = payload.headers.get('Content-Transfer-Encoding', '').lower()
    return cte in ('', 'base64', 'quoted-printable', 'binary')

Try / catch

try:
    writer.append_payload(payload)
except RuntimeError:
    payload.headers.pop('Content-Transfer-Encoding', None)
    writer.append_payload(payload)

Prevention

When it happens

Trigger: Appending a Payload whose headers set Content-Transfer-Encoding to e.g. '8bit', '7bit', 'uuencode', or a typo, on a non-form-data MultipartWriter. Note: form-data writers assert that Content-Transfer-Encoding is absent (RFC 7578 §4.8).

Common situations: Forwarding MIME-style parts that include 7bit/8bit transfer encoding; manually setting Content-Transfer-Encoding to a value the writer doesn't serialize; copy-pasting email headers into HTTP multipart.

Related errors


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