aio-libs/aiohttp · error · ValueError
boundary should contain ASCII only chars
Error message
boundary should contain ASCII only chars
What it means
Raised by MultipartWriter.__init__ when the user-supplied boundary string cannot be encoded as ASCII. The Payload API requires the boundary to be a str convertible losslessly to bytes, so non-ASCII characters are rejected up front.
Source
Thrown at aiohttp/multipart.py:924
class MultipartWriter(Payload):
"""Multipart body writer."""
_value: None
# _consumed = False (inherited) - Can be encoded multiple times
_autoclose = True # No file handles, just collects parts in memory
def __init__(self, subtype: str = "mixed", boundary: str | None = None) -> None:
boundary = boundary if boundary is not None else uuid.uuid4().hex
# The underlying Payload API demands a str (utf-8), not bytes,
# so we need to ensure we don't lose anything during conversion.
# As a result, require the boundary to be ASCII only.
# In both situations.
try:
self._boundary = boundary.encode("ascii")
except UnicodeEncodeError:
raise ValueError("boundary should contain ASCII only chars") from None
if len(boundary) > 70:
raise ValueError("boundary %r is too long (70 chars max)" % boundary)
ctype = f"multipart/{subtype}; boundary={self._boundary_value}"
super().__init__(None, content_type=ctype)
self._parts: list[_Part] = []
self._is_form_data = subtype == "form-data"
def __enter__(self) -> "MultipartWriter":
return self
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_val: BaseException | None,View on GitHub (pinned to c0ef574e29)
Solutions
- Use an ASCII-only boundary: `MultipartWriter(boundary='----WebKitFormBoundary7MA4YWxk')`.
- Omit the boundary argument entirely — MultipartWriter generates a random ASCII uuid4 hex by default.
- Sanitize user-provided boundary input to ASCII before passing it.
Example fix
// before w = MultipartWriter(boundary='——boundary——') # non-ASCII em-dashes // after w = MultipartWriter() # auto-generated ASCII boundary
Defensive patterns
Strategy: validation
Validate before calling
try:
boundary.encode('ascii')
except UnicodeEncodeError:
raise ValueError('boundary must be ASCII-only') Type guard
def is_ascii_boundary(b: str) -> bool:
try:
b.encode('ascii')
return True
except UnicodeEncodeError:
return False Try / catch
try:
writer = MultipartWriter(boundary=boundary)
except ValueError:
writer = MultipartWriter() # fall back to auto-generated ASCII boundary Prevention
- Prefer the auto-generated boundary unless you have a specific reason.
- Sanitize any dynamic boundary to ASCII before passing it.
- Avoid copying boundaries from untrusted sources.
When it happens
Trigger: Constructing `MultipartWriter(boundary='…')` with a boundary containing non-ASCII characters (e.g. Unicode dashes, emoji, accented letters). The encode('ascii') call fails and the UnicodeEncodeError is converted to a ValueError.
Common situations: Copy-pasting a fancy boundary with typographic characters; auto-generating a boundary from user input that contains Unicode; test fixtures using arbitrary strings.
Related errors
- boundary value contains invalid characters
- Reader did not read all the data or it is malformed
- Reading after EOF
- boundary missed for Content-Type: %s
- boundary %r is too long (70 chars max)
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/74e55085e55a6e54.json.
Report an issue: GitHub.