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
- Remove the Content-Transfer-Encoding header from the payload before appending and let aiohttp manage encoding (delete payload.headers[CONTENT_TRANSFER_ENCODING]).
- If you must set it, use one of 'base64', 'quoted-printable', or 'binary' (note 'binary' is internally normalized to None).
- 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
- Never copy raw MIME headers from inbound messages onto outbound multipart parts.
- Let MultipartWriter manage Content-Transfer-Encoding unless you explicitly need base64/quoted-printable.
- Validate any header set from user/config data against the allowed set before appending.
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
- boundary missed for Content-Type
- boundary %r is too long (70 chars max)
- boundary should contain ASCII only chars
- boundary value contains invalid characters
- content_type must be an instance of str. Got
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)