{"id":"9a1938c9700e73c1","repo":"aio-libs/aiohttp","slug":"unable-to-decode","errorCode":null,"errorMessage":"Unable to decode.","messagePattern":"Unable to decode\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/multipart.py","lineNumber":652,"sourceCode":"@payload_type(BodyPartReader, order=Order.try_first)\nclass BodyPartReaderPayload(Payload):\n    _value: BodyPartReader\n    # _autoclose = False (inherited) - Streaming reader that may have resources\n\n    def __init__(self, value: BodyPartReader, *args: Any, **kwargs: Any) -> None:\n        super().__init__(value, *args, **kwargs)\n\n        params: dict[str, str] = {}\n        if value.name is not None:\n            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        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","sourceCodeStart":634,"sourceCodeEnd":670,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/multipart.py#L634-L670","documentation":"Raised unconditionally by BodyPartReaderPayload.decode(). BodyPartReaderPayload is a streaming Payload wrapper around a BodyPartReader; it cannot materialize its full content as a string because the underlying stream may be arbitrarily large and can only be consumed once. The method exists only to satisfy the Payload ABC contract and deliberately rejects synchronous decoding.","triggerScenarios":"Calling `.decode()` on a payload obtained from a BodyPartReader (e.g. when a BodyPartReader is registered as a payload via @payload_type and then someone calls payload.decode()). Happens in generic payload-handling code that assumes all Payload subclasses support decode().","commonSituations":"Generic middleware that calls `.decode()` on every payload; test helpers serializing payloads to strings; copying a BodyPartReader into another request body via a path that tries to buffer the whole thing.","solutions":["Do not call decode() on streaming payloads — consume them via `await payload.write(writer)` instead.","If you need bytes, switch to a non-streaming payload (BytesPayload) by first reading the part into memory: `data = await part.read(decode=True)`.","Type-check with isinstance(payload, BodyPartReaderPayload) before calling decode() in generic code."],"exampleFix":"// before\ntext = payload.decode()\n// after\nbuf = io.BytesIO()\nawait payload.write(StreamWriter(buf))  # stream-consume instead\ntext = buf.getvalue().decode('utf-8')\n","handlingStrategy":"type-guard","validationCode":"from aiohttp.multipart import BodyPartReaderPayload\nif isinstance(payload, BodyPartReaderPayload):\n    raise TypeError('use write() to consume streaming payloads')","typeGuard":"from aiohttp.multipart import BodyPartReaderPayload\n\ndef is_streaming_payload(p) -> bool:\n    return isinstance(p, BodyPartReaderPayload)","tryCatchPattern":"try:\n    text = payload.decode()\nexcept TypeError:\n    # streaming payload — consume via write()\n    buf = io.BytesIO()\n    await payload.write(StreamWriter(buf))\n    text = buf.getvalue().decode('utf-8')","preventionTips":["Never call decode()/as_bytes() on payloads of unknown type without an isinstance check.","In generic middleware, branch on BodyPartReaderPayload before buffering.","Prefer the write() contract for all payload consumption."],"tags":["multipart","payload","streaming","api-misuse"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}