{"record":{"id":"a6e2d66a0a2f299f","repo":"aio-libs/aiohttp","slug":"unable-to-read-body-part-as-bytes-use-write-to","errorCode":null,"errorMessage":"Unable to read body part as bytes. Use write() to consume.","messagePattern":"Unable to read body part as bytes\\. Use write\\(\\) to consume\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/multipart.py","lineNumber":662,"sourceCode":"            params[\"name\"] = value.name\n        if value.filename is not None:\n            params[\"filename\"] = value.filename\n\n        if params:\n            self.set_content_disposition(\"attachment\", True, **params)\n\n    def decode(self, encoding: str = \"utf-8\", errors: str = \"strict\") -> str:\n        raise TypeError(\"Unable to decode.\")\n\n    async def as_bytes(self, encoding: str = \"utf-8\", errors: str = \"strict\") -> bytes:\n        \"\"\"Raises TypeError as body parts should be consumed via write().\n\n        This is intentional: BodyPartReader payloads are designed for streaming\n        large data (potentially gigabytes) and must be consumed only once via\n        the write() method to avoid memory exhaustion. They cannot be buffered\n        in memory for reuse.\n        \"\"\"\n        raise TypeError(\"Unable to read body part as bytes. Use write() to consume.\")\n\n    async def write(self, writer: AbstractStreamWriter) -> None:\n        field = self._value\n        # Reading the part drains the underlying stream irreversibly, so mark the\n        # payload consumed up front: even an interrupted write leaves nothing that\n        # a retry or redirect could replay.\n        self._consumed = True\n        while chunk := await field.read_chunk(size=DEFAULT_CHUNK_SIZE):\n            async for d in field.decode_iter(chunk):\n                await writer.write(d)\n\n\nclass MultipartReader:\n    \"\"\"Multipart body reader.\"\"\"\n\n    #: Response wrapper, used when multipart readers constructs from response.\n    response_wrapper_cls = MultipartResponseWrapper\n    #: Multipart reader class, used to handle multipart/* body parts.","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/multipart.py#L644-L680","documentation":"BodyPartReaderPayload.as_bytes() unconditionally raises TypeError. Because the underlying BodyPartReader streams potentially gigabytes and can only be consumed once, buffering it into bytes would risk memory exhaustion and break single-consumption semantics.","triggerScenarios":"Calling await payload.as_bytes() on a BodyPartReaderPayload, or handing such a payload to code that calls as_bytes() (e.g. some serializer or test helper).","commonSituations":"Treating a streaming multipart part like an in-memory payload; test code that calls as_bytes() to assert on content; frameworks that auto-buffer payloads.","solutions":["Use await payload.write(writer) to stream the part to a file/response/IO writer.","If you must have bytes and the part is known small, drain it manually: buf = io.BytesIO(); writer = StreamResponse(...); await payload.write(BytesWriter(buf)).","Replace the BodyPartReaderPayload with a BytesPayload built from explicitly read bytes when buffering is acceptable."],"exampleFix":"// before\ndata = await payload.as_bytes()\n\n// after\nbuf = io.BytesIO()\nclass W(AbstractStreamWriter):\n    async def write(self, chunk): buf.write(chunk)\nawait payload.write(W())\ndata = buf.getvalue()","handlingStrategy":"type-guard","validationCode":"from aiohttp.multipart import BodyPartReaderPayload\n\nasync def to_bytes(payload) -> bytes:\n    if isinstance(payload, BodyPartReaderPayload):\n        buf = bytearray()\n        class W(AbstractStreamWriter):\n            async def write(self, chunk): buf.extend(chunk)\n            async def write_headers(self, *a, **k): ...\n            async def write_eof(self, *a, **k): ...\n        await payload.write(W())\n        return bytes(buf)\n    return await payload.as_bytes()","typeGuard":"from aiohttp.multipart import BodyPartReaderPayload\n\ndef is_streaming_payload(p: object) -> bool:\n    return isinstance(p, BodyPartReaderPayload)","tryCatchPattern":"try:\n    data = await payload.as_bytes()\nexcept TypeError as e:\n    if 'Use write()' in str(e):\n        data = await stream_to_bytes(payload)\n    else:\n        raise","preventionTips":["Use write() to stream BodyPartReaderPayload to a file/response writer.","Type-check before calling as_bytes() on arbitrary payloads.","For small known parts, read chunks explicitly into a buffer rather than as_bytes()."],"tags":["multipart","payload","streaming","typeerror","memory","api-misuse"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}