aio-libs/aiohttp · error · RuntimeError
unknown content transfer encoding
Error message
unknown content transfer encoding: {encoding} What it means
Raised by _decode_content_transfer when the Content-Transfer-Encoding header is not one of base64, quoted-printable, binary, 8bit, or 7bit. Any other token (or a misspelling) yields a RuntimeError.
Solutions
- Use one of base64, quoted-printable, binary, 8bit, 7bit for Content-Transfer-Encoding.
- If you control the producer, drop CTE and send 8bit/binary with correct Content-Length.
- Decode the unsupported transfer encoding externally before/after the reader touches it.
- Catch RuntimeError and fall back to raw bytes when CTE is non-standard.
Example fix
// before Content-Transfer-Encoding: x-uuencode // after Content-Transfer-Encoding: base64
Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED_CTE = {'base64', 'quoted-printable', 'binary', '8bit', '7bit'}
def assert_supported_cte(headers):
cte = headers.get('Content-Transfer-Encoding', '').lower()
if cte and cte not in SUPPORTED_CTE:
raise ValueError(f'Unsupported Content-Transfer-Encoding: {cte}') Type guard
def is_supported_cte(value: object) -> bool:
return isinstance(value, str) and value.lower() in {'base64', 'quoted-printable', 'binary', '8bit', '7bit'} Try / catch
try:
data = part._decode_content_transfer(raw)
except RuntimeError as e:
if 'transfer encoding' in str(e):
data = raw # treat as binary
else:
raise Prevention
- Use standard MIME CTE tokens (base64, quoted-printable, binary, 8bit, 7bit).
- Spell tokens exactly (no 'base-64').
- Drop CTE on the producer side if parts are already 8bit-clean.
When it happens
Trigger: A part carrying Content-Transfer-Encoding such as 'x-uuencode', 'uuencode', 'base-64' (hyphen), or any vendor extension; an empty/odd value that does not match the allowed set.
Common situations: Legacy MIME producers; copy-paste typos; MIME-aware mail clients repurposed for HTTP multipart; custom CTE tokens.
Related errors
- unknown content encoding
- unknown content transfer encoding
- boundary missed for Content-Type
- boundary %r is too long (70 chars max)
- boundary should contain ASCII only chars
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/d3ad72dead8be317.
Report an issue: GitHub.
Appendix: 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 d041d4d0fd)