aio-libs/aiohttp · error · RuntimeError

unknown content transfer encoding

Error message

unknown content transfer encoding: {te_encoding}

What it means

Raised by MultipartWriter when a payload being appended carries a Content-Transfer-Encoding header whose value is not one of the allowed MIME transfer encodings. aiohttp only understands '', 'base64', 'quoted-printable', and 'binary' so it refuses to serialize a part it cannot correctly encode on the wire. The check exists because multipart bodies must be encoded deterministically and an unknown transfer encoding would produce a corrupt, undecodable message.

Solutions

  1. Remove the Content-Transfer-Encoding header from the payload before appending and let aiohttp manage encoding (delete payload.headers[CONTENT_TRANSFER_ENCODING]).
  2. If you must set it, use one of 'base64', 'quoted-printable', or 'binary' (note 'binary' is internally normalized to None).
  3. Sanitize/normalize the header value to lowercase and validate against the allowed set before calling append().

Example fix

# before
payload.headers['Content-Transfer-Encoding'] = '7bit'
writer.append(payload)

# after
del payload.headers['Content-Transfer-Encoding']  # let aiohttp decide
writer.append(payload)
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED_TE = {'', 'base64', 'quoted-printable', 'binary'}
te = payload.headers.get('Content-Transfer-Encoding', '').lower()
if te not in ALLOWED_TE:
    payload.headers.pop('Content-Transfer-Encoding', None)
writer.append(payload)

Type guard

def is_supported_te(headers: multidict.CIMultiDict) -> bool:
    return headers.get('Content-Transfer-Encoding', '').lower() in {'', 'base64', 'quoted-printable', 'binary'}

Try / catch

try:
    writer.append(payload)
except RuntimeError as e:
    if 'unknown content transfer encoding' in str(e):
        payload.headers.pop('Content-Transfer-Encoding', None)
        writer.append(payload)
    else:
        raise

Prevention

When it happens

Trigger: Calling MultipartWriter.append(payload) (or append_json/append_form with pre-set headers) where payload.headers['Content-Transfer-Encoding'] is set to a value like '7bit', '8bit', 'uuencode', 'x-uuencode', or '16bit'. Also triggered by copying headers verbatim from an inbound email-style MIME message onto an outbound part.

Common situations: Porting email (email.mime) code to aiohttp multipart, where 7bit/8bit are common defaults; forwarding headers from a parsed incoming multipart request without filtering; setting the header manually from user input or config.

Related errors


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

Appendix: source

Thrown at aiohttp/multipart.py:1045

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