aio-libs/aiohttp · error · ValueError
boundary %r is too long (70 chars max)
Error message
boundary %r is too long (70 chars max)
What it means
Raised by MultipartReader._get_boundary() when the boundary parameter extracted from the Content-Type header exceeds 70 characters. RFC 2046 §5.1.1 caps boundary length at 70 characters, so aiohttp enforces this on the reader side to reject malformed/abusive bodies before processing.
Source
Thrown at aiohttp/multipart.py:837
max_field_size=self._max_field_size,
max_headers=self._max_headers,
max_size_error_cls=self._max_size_error_cls,
)
else:
return self.part_reader_cls(
self._boundary,
headers,
self._content,
subtype=self._mimetype.subtype,
default_charset=self._default_charset,
client_max_size=self._client_max_size,
max_size_error_cls=self._max_size_error_cls,
)
def _get_boundary(self) -> str:
boundary = self._mimetype.parameters["boundary"]
if len(boundary) > 70:
raise ValueError("boundary %r is too long (70 chars max)" % boundary)
return boundary
async def _readline(self) -> bytes:
if self._unread:
return self._unread.pop()
return await self._content.readline()
async def _read_until_first_boundary(self) -> None:
while True:
chunk = await self._readline()
if chunk == b"":
raise ValueError(f"Could not find starting boundary {self._boundary!r}")
chunk = chunk.rstrip()
if chunk == self._boundary:
return
elif chunk == self._boundary + b"--":
self._at_eof = TrueView on GitHub (pinned to c0ef574e29)
Solutions
- Fix the sender to emit a boundary ≤ 70 characters (RFC 2046 limit).
- If you cannot change the sender, reject the message before parsing based on Content-Type inspection.
- Treat the ValueError as a 400 Bad Request in handlers.
Example fix
// before reader = await response.multipart() # boundary 80 chars -> ValueError // after # fix the writer side: writer = MultipartWriter(boundary='short-boundary') # <= 70 chars
Defensive patterns
Strategy: validation
Validate before calling
import re
m = re.search(r'boundary=([^;]+)', response.headers.get('Content-Type', ''))
if m and len(m.group(1).strip('"')) > 70:
raise ValueError('boundary exceeds RFC 2046 limit') Type guard
def boundary_within_limit(content_type: str) -> bool:
import re
m = re.search(r'boundary=([^;]+)', content_type)
return bool(m) and len(m.group(1).strip('"')) <= 70 Try / catch
try:
reader = await response.multipart()
except ValueError as e:
if 'too long' in str(e):
return web.Response(status=400, text='boundary too long')
raise Prevention
- Inspect boundary length before constructing the reader.
- Reject overlong boundaries as protocol violations.
- Educate upstream on the 70-char RFC limit.
When it happens
Trigger: Receiving a multipart response/request whose Content-Type boundary parameter is longer than 70 chars. Constructed during MultipartReader.__init__ via _get_boundary().
Common situations: A buggy sender generating overlong boundaries; an attacker crafting a header-bomb style boundary; a misconfigured framework concatenating data into the boundary.
Related errors
- boundary missed for Content-Type: %s
- Could not find starting boundary {self._boundary!r}
- Invalid boundary {chunk!r}, expected {self._boundary!r}
- boundary value contains invalid characters
- filename must be an instance of str. Got: %s
AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04).
Data as JSON: /data/errors/1880818c3e2a2de5.json.
Report an issue: GitHub.