{"id":"ec50413820657ea7","repo":"aio-libs/aiohttp","slug":"reader-did-not-read-all-the-data-or-it-is-malforme","errorCode":null,"errorMessage":"Reader did not read all the data or it is malformed","messagePattern":"Reader did not read all the data or it is malformed","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/multipart.py","lineNumber":395,"sourceCode":"                if self._prev_chunk:\n                    over_chunk = self._prev_chunk[:over_chunk_size]\n                    self._prev_chunk = self._prev_chunk[len(over_chunk) :]\n\n                if len(over_chunk) != over_chunk_size:\n                    over_chunk += await self._content.read(4 - len(over_chunk))\n\n                if not over_chunk:\n                    self._at_eof = True\n\n                stripped_chunk += b\"\".join(over_chunk.split())\n                chunk += over_chunk\n                remainder = len(stripped_chunk) % 4\n\n        self._read_bytes += len(chunk)\n        if self._read_bytes == self._length:\n            self._at_eof = True\n        if self._at_eof and await self._content.readline() != b\"\\r\\n\":\n            raise ValueError(\"Reader did not read all the data or it is malformed\")\n        return chunk\n\n    async def _read_chunk_from_length(self, size: int) -> bytes:\n        # Reads body part content chunk of the specified size.\n        # The body part must has Content-Length header with proper value.\n        assert self._length is not None, \"Content-Length required for chunked read\"\n        chunk_size = min(size, self._length - self._read_bytes)\n        chunk = await self._content.read(chunk_size)\n        if self._content.at_eof():\n            self._at_eof = True\n        return chunk\n\n    async def _read_chunk_from_stream(self, size: int) -> bytes:\n        # Reads content chunk of body part with unknown length.\n        # The Content-Length header for body part is not necessary.\n        assert (\n            size >= self._boundary_len\n        ), \"Chunk size must be greater or equal than boundary length + 2\"","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/multipart.py#L377-L413","documentation":"ValueError raised by BodyPartReader.read_chunk when, after a part reaches EOF, the expected trailing CRLF separator after the part body is not present. This means the multipart framing is malformed — extra/missing bytes around the boundary.","triggerScenarios":"After reading the part body to EOF (read_bytes == length or stream EOF), read_chunk reads the next line and expects b'\\r\\n'; if it differs (missing CRLF, extra data, boundary mismatch), ValueError is raised.","commonSituations":"Malformed multipart body (missing CRLF between part and boundary); wrong/duplicate boundary; a part whose Content-Length is wrong so framing desynchronises; hand-crafted multipart with bad separators.","solutions":["Verify the multipart boundary matches the Content-Type boundary parameter exactly.","Check that each part is followed by \\r\\n before the boundary.","Ensure Content-Length per part matches the actual body size.","Regenerate the payload from a known-good encoder."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    async for part in reader:\n        data = await part.read()\nexcept ValueError:\n    return web.Response(status=400, text='malformed multipart')","preventionTips":["Use a standards-compliant multipart encoder.","Keep per-part Content-Length accurate.","Validate the boundary string matches."],"tags":["multipart","framing","boundary","malformed","parser"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}