{"record":{"id":"ccfbc5ab34f1ec0d","repo":"aio-libs/aiohttp","slug":"to-decode-nested-multipart-you-need-to-use-custom","errorCode":null,"errorMessage":"To decode nested multipart you need to use custom reader","messagePattern":"To decode nested multipart you need to use custom reader","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/web_request.py","lineNumber":802,"sourceCode":"                        raw_data = bytearray()\n                        while chunk := await field.read_chunk():\n                            size += len(chunk)\n                            if 0 < max_size < size:\n                                raise HTTPRequestEntityTooLarge(max_size)\n                            raw_data.extend(chunk)\n\n                        value = bytearray()\n                        # form-data doesn't support compression, so don't need to check size again.\n                        async for d in field.decode_iter(raw_data):  # type: ignore[arg-type]\n                            value.extend(d)\n\n                        if field_ct is None or field_ct.startswith(\"text/\"):\n                            charset = field.get_charset(default=\"utf-8\")\n                            out.add(field.name, value.decode(charset))\n                        else:\n                            out.add(field.name, value)  # type: ignore[arg-type]\n                else:\n                    raise ValueError(\n                        \"To decode nested multipart you need to use custom reader\",\n                    )\n        else:\n            data = await self.read()\n            if data:\n                charset = self.charset or \"utf-8\"\n                bytes_query = data.rstrip()\n                try:\n                    query = bytes_query.decode(charset)\n                except (LookupError, UnicodeDecodeError):\n                    raise HTTPUnsupportedMediaType()\n                out.extend(\n                    parse_qsl(qs=query, keep_blank_values=True, encoding=charset)\n                )\n\n        self._post = MultiDictProxy(out)\n        return self._post\n","sourceCodeStart":784,"sourceCodeEnd":820,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/web_request.py#L784-L820","documentation":"BaseRequest.post() only handles a single level of multipart/form-data. If a part is itself a MultipartReader (nested multipart, e.g. multipart/mixed or message/rfc822 inside form-data), it raises ValueError directing you to use a custom reader. post() will not recurse into nested multipart.","triggerScenarios":"A multipart/form-data body containing a nested multipart/* part (aggregate payloads, email-style submissions, RFC 7578 nested examples).","commonSituations":"Clients composing multiple files under one field with multipart/mixed; email gateways; aggregate document uploads.","solutions":["Use request.multipart() directly and walk the reader yourself to handle nested parts.","Do not call post() for nested multipart; write a dedicated parser.","Reject nested multipart with 400 if your API does not support it."],"exampleFix":"# before\ndata = await request.post()  # raises on nested multipart\n# after\nreader = await request.multipart()\nasync for part in reader:\n    if isinstance(part, MultipartReader):\n        # handle nested multipart manually\n        ...","handlingStrategy":"validation","validationCode":"if request.content_type == 'multipart/form-data':\n    # peek for nested multipart before calling post()\n    reader = await request.multipart()\n    # handle nested parts manually","typeGuard":"def needs_custom_reader(part: object) -> bool:\n    return not isinstance(part, BodyPartReader)","tryCatchPattern":"try:\n    data = await request.post()\nexcept ValueError:\n    # fall back to a custom multipart reader\n    reader = await request.multipart()","preventionTips":["Use request.multipart() directly when nested parts are possible.","Reject nested multipart with 400 if your API does not support it.","Document that post() supports only flat multipart/form-data."],"tags":["multipart","nested","form-data","parser"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}