aio-libs/aiohttp · error · RuntimeError
unknown content transfer encoding: {encoding}
Error message
unknown content transfer encoding: {encoding} What it means
Raised by BodyPartReader._decode_content_transfer when a part's Content-Transfer-Encoding header is not one of the recognized values (base64, quoted-printable, binary, 8bit, 7bit). This method runs whenever a part has a Content-Transfer-Encoding header and the bytes need to be decoded.
Source
Thrown at aiohttp/multipart.py:607
suppress_deflate_header=True,
)
yield await d.decompress(data, max_length=self._max_decompress_size)
while d.data_available:
yield await d.decompress(b"", max_length=self._max_decompress_size)
else:
raise RuntimeError(f"unknown content encoding: {encoding}")
def _decode_content_transfer(self, data: bytes) -> bytes:
encoding = self.headers.get(CONTENT_TRANSFER_ENCODING, "").lower()
if encoding == "base64":
return base64.b64decode(data)
elif encoding == "quoted-printable":
return binascii.a2b_qp(data)
elif encoding in ("binary", "8bit", "7bit"):
return data
else:
raise RuntimeError(f"unknown content transfer encoding: {encoding}")
def get_charset(self, default: str) -> str:
"""Returns charset parameter from Content-Type header or default."""
ctype = self.headers.get(CONTENT_TYPE, "")
mimetype = parse_mimetype(ctype)
return mimetype.parameters.get("charset", self._default_charset or default)
@reify
def name(self) -> str | None:
"""Returns name specified in Content-Disposition header.
If the header is missing or malformed, returns None.
"""
_, params = parse_content_disposition(self.headers.get(CONTENT_DISPOSITION))
return content_disposition_filename(params, "name")
@reify
def filename(self) -> str | None:View on GitHub (pinned to c0ef574e29)
Solutions
- Correct or remove the Content-Transfer-Encoding header on the sender so it is one of base64/quoted-printable/binary/8bit/7bit.
- If you must handle a custom encoding, read raw bytes with `await part.read(decode=False)` (note: this still calls transfer decoding — delete the header from part.headers first), then decode manually.
- Pre-validate part.headers before consuming the part.
Example fix
// before data = await part.read(decode=True) # Content-Transfer-Encoding: uuencode // after del part.headers['Content-Transfer-Encoding'] raw = await part.read(decode=False) data = uu_decode(raw)
Defensive patterns
Strategy: validation
Validate before calling
cte = part.headers.get('Content-Transfer-Encoding', '').lower()
if cte and cte not in ('base64', 'quoted-printable', 'binary', '8bit', '7bit'):
raise UnsupportedEncoding(f'unsupported CTE: {cte}') Type guard
def is_supported_cte(part) -> bool:
cte = part.headers.get('Content-Transfer-Encoding', '').lower()
return cte in ('', 'base64', 'quoted-printable', 'binary', '8bit', '7bit') Try / catch
try:
data = await part.read(decode=True)
except RuntimeError as e:
if 'unknown content transfer encoding' in str(e):
del part.headers['Content-Transfer-Encoding']
data = await part.read(decode=False)
else:
raise Prevention
- Whitelist Content-Transfer-Encoding values at ingestion.
- Reject MIME-only encodings (uuencode, x-*) before they reach the reader.
- For form-data, CTE should be absent entirely.
When it happens
Trigger: A received multipart part carries a Content-Transfer-Encoding header with an unrecognized token (e.g. 'uuencode', 'x-gzip', 'base-64' typo, or any custom value). Surfaced during `await part.read(decode=True)` / `part.decode(data)` because _apply_content_transfer_decoding is always applied when the header is present.
Common situations: Mail-style MIME parts forwarded into HTTP; legacy clients sending non-standard transfer encodings; typo in the header value; a gateway adding an encoding aiohttp does not implement.
Related errors
- unknown content transfer encoding: {te_encoding}
- unknown content encoding: {encoding}
- filename must be an instance of str. Got: %s
- content_type must be an instance of str. Got: %s
- Only io.IOBase, multidict and (name, file) pairs allowed, us
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/d3ad72dead8be317.json.
Report an issue: GitHub.