aio-libs/aiohttp · error · ValueError
boundary missed for Content-Type: %s
Error message
boundary missed for Content-Type: %s
What it means
Raised by MultipartReader.__init__ when the Content-Type header indicates a multipart/* type but lacks the required 'boundary' parameter. Per RFC 2046 §5.1.1 the boundary delimiter is mandatory for multipart bodies, so the reader cannot segment the stream without it.
Source
Thrown at aiohttp/multipart.py:695
#: None points to type(self)
multipart_reader_cls: type["MultipartReader"] | None = None
#: Body part reader class for non multipart/* content types.
part_reader_cls = BodyPartReader
def __init__(
self,
headers: Mapping[str, str],
content: StreamReader,
*,
client_max_size: int = sys.maxsize,
max_field_size: int = 8190,
max_headers: int = 128,
max_size_error_cls: type[Exception] = ValueError,
) -> None:
self._mimetype = parse_mimetype(headers[CONTENT_TYPE])
assert self._mimetype.type == "multipart", "multipart/* content type expected"
if "boundary" not in self._mimetype.parameters:
raise ValueError(
"boundary missed for Content-Type: %s" % headers[CONTENT_TYPE]
)
self.headers = headers
self._boundary = ("--" + self._get_boundary()).encode()
self._client_max_size = client_max_size
self._content = content
self._default_charset: str | None = None
self._last_part: MultipartReader | BodyPartReader | None = None
self._max_field_size = max_field_size
self._max_headers = max_headers
self._max_size_error_cls = max_size_error_cls
self._at_eof = False
self._at_bof = True
self._unread: list[bytes] = []
def __aiter__(self) -> Self:
return selfView on GitHub (pinned to c0ef574e29)
Solutions
- Ensure the sender includes a valid boundary in the Content-Type header.
- If you control the response, use MultipartWriter which generates the boundary automatically.
- Validate the Content-Type header before calling multipart() and reject with a clear error.
Example fix
// before
reader = await response.multipart() # no boundary -> ValueError
// after
if 'boundary=' not in response.headers.get('Content-Type', ''):
raise ValueError('upstream omitted multipart boundary')
reader = await response.multipart()
Defensive patterns
Strategy: validation
Validate before calling
ctype = response.headers.get('Content-Type', '')
if 'multipart/' in ctype and 'boundary=' not in ctype:
raise ValueError('Content-Type missing boundary parameter') Type guard
import re
def has_boundary(content_type: str) -> bool:
return bool(re.search(r'boundary=', content_type, re.I)) Try / catch
try:
reader = await response.multipart()
except ValueError as e:
# missing boundary — reject upstream
raise BadUpstream(str(e)) Prevention
- Validate Content-Type contains a boundary before calling multipart().
- Use MultipartWriter on the producer side so the boundary is always set.
- Reject multipart responses lacking a boundary at the client boundary.
When it happens
Trigger: Constructing a MultipartReader (directly or via `response.multipart()` / `request.multipart()`) where the Content-Type is e.g. 'multipart/form-data' with no `; boundary=...`. The assert for multipart type passes but the boundary check fails.
Common situations: Upstream sends `Content-Type: multipart/form-data` and forgets the boundary (bug); a proxy strips the boundary parameter; manually crafted responses/requests; Content-Type header truncated by a size limit.
Related errors
- boundary %r is too long (70 chars max)
- Could not find starting boundary {self._boundary!r}
- Invalid boundary {chunk!r}, expected {self._boundary!r}
- content_type must be an instance of str. Got: %s
- Reader did not read all the data or it is malformed
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/cf11ef0a13815650.json.
Report an issue: GitHub.