{"record":{"id":"cf11ef0a13815650","repo":"aio-libs/aiohttp","slug":"boundary-missed-for-content-type-s","errorCode":null,"errorMessage":"boundary missed for Content-Type: %s","messagePattern":"boundary missed for Content-Type: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/multipart.py","lineNumber":699,"sourceCode":"    #: None points to type(self)\n    multipart_reader_cls: type[\"MultipartReader\"] | None = None\n    #: Body part reader class for non multipart/* content types.\n    part_reader_cls = BodyPartReader\n\n    def __init__(\n        self,\n        headers: Mapping[str, str],\n        content: StreamReader,\n        *,\n        client_max_size: int = sys.maxsize,\n        max_field_size: int = 8190,\n        max_headers: int = 128,\n        max_size_error_cls: type[Exception] = ValueError,\n    ) -> None:\n        self._mimetype = parse_mimetype(headers[CONTENT_TYPE])\n        assert self._mimetype.type == \"multipart\", \"multipart/* content type expected\"\n        if \"boundary\" not in self._mimetype.parameters:\n            raise ValueError(\n                \"boundary missed for Content-Type: %s\" % headers[CONTENT_TYPE]\n            )\n\n        self.headers = headers\n        self._boundary = (\"--\" + self._get_boundary()).encode()\n        self._client_max_size = client_max_size\n        self._content = content\n        self._default_charset: str | None = None\n        self._last_part: MultipartReader | BodyPartReader | None = None\n        self._max_field_size = max_field_size\n        self._max_headers = max_headers\n        self._max_size_error_cls = max_size_error_cls\n        self._at_eof = False\n        self._at_bof = True\n        self._unread: list[bytes] = []\n\n    def __aiter__(self) -> Self:\n        return self","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/multipart.py#L681-L717","documentation":"MultipartReader.__init__ requires the Content-Type to be multipart/* and to carry a 'boundary' parameter. If parse_mimetype finds no boundary in the parameters, ValueError is raised because multipart framing cannot proceed without it.","triggerScenarios":"Constructing MultipartReader from headers whose Content-Type is 'multipart/form-data' (or mixed/related) with no ';boundary=...' token, or where the boundary parameter is malformed by the parser.","commonSituations":"A server/proxy stripping the boundary from Content-Type; a client forwarding multipart headers incompletely; malformed requests crafted to test error handling; Content-Type set manually without boundary.","solutions":["Ensure the request/response Content-Type includes a valid boundary parameter, e.g. 'multipart/form-data; boundary=----xyz'.","When building requests with MultipartWriter, let the writer generate the Content-Type (it embeds the boundary) rather than setting one manually.","Before constructing MultipartReader, check parse_mimetype(content_type).parameters for 'boundary' and reject early with a clear 400.","Forward the full Content-Type header through proxies without modification."],"exampleFix":"// before\nContent-Type: multipart/form-data\n\n// after\nContent-Type: multipart/form-data; boundary=----WebKitFormBoundary","handlingStrategy":"validation","validationCode":"from aiohttp.hdrs import CONTENT_TYPE\nfrom aiohttp.multipart import parse_mimetype\n\ndef has_boundary(content_type: str) -> bool:\n    mt = parse_mimetype(content_type)\n    return mt.type == 'multipart' and 'boundary' in mt.parameters\n\n# at the request boundary\nif not has_boundary(request.headers.get(CONTENT_TYPE, '')):\n    return web.Response(status=400, text='multipart Content-Type missing boundary')","typeGuard":"def is_multipart_with_boundary(content_type: object) -> bool:\n    if not isinstance(content_type, str):\n        return False\n    mt = parse_mimetype(content_type)\n    return mt.type == 'multipart' and bool(mt.parameters.get('boundary'))","tryCatchPattern":"try:\n    reader = MultipartReader(request.headers, request.content)\nexcept ValueError as e:\n    return web.Response(status=400, text=str(e))","preventionTips":["Always set a boundary when constructing multipart Content-Type headers manually.","Let MultipartWriter generate the Content-Type so the boundary is always present.","Forward Content-Type through proxies unchanged."],"tags":["multipart","content-type","boundary","validation","rfc-2046"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}