{"record":{"id":"8c9d8667e471d70c","repo":"aio-libs/aiohttp","slug":"unable-to-decode-content-not-cached-call-as-byt","errorCode":null,"errorMessage":"Unable to decode - content not cached. Call as_bytes() first.","messagePattern":"Unable to decode - content not cached\\. Call as_bytes\\(\\) first\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"aiohttp/payload.py","lineNumber":1078,"sourceCode":"                if remaining_bytes is None:\n                    await writer.write(chunk)\n                # If we have a content length limit\n                elif remaining_bytes > 0:\n                    await writer.write(chunk[:remaining_bytes])\n                    remaining_bytes -= len(chunk)\n                # We still want to exhaust the iterator even\n                # if we have reached the content length limit\n                # since the file handle may not get closed by\n                # the iterator if we don't do this\n        except StopAsyncIteration:\n            # Iterator is exhausted\n            self._iter = None\n\n    def decode(self, encoding: str = \"utf-8\", errors: str = \"strict\") -> str:\n        \"\"\"Decode the payload content as a string if cached chunks are available.\"\"\"\n        if self._cached_chunks is not None:\n            return b\"\".join(self._cached_chunks).decode(encoding, errors)\n        raise TypeError(\"Unable to decode - content not cached. Call as_bytes() first.\")\n\n    async def as_bytes(self, encoding: str = \"utf-8\", errors: str = \"strict\") -> bytes:\n        \"\"\"\n        Return bytes representation of the value.\n\n        This method reads the entire async iterable content and returns it as bytes.\n        It generates and caches the chunks for future reuse.\n        \"\"\"\n        # If we have cached chunks, return them joined\n        if self._cached_chunks is not None:\n            return b\"\".join(self._cached_chunks)\n\n        # If iterator is exhausted and no cache, return empty\n        if self._iter is None:\n            return b\"\"\n\n        # Read all chunks and cache them\n        chunks: list[bytes] = []","sourceCodeStart":1060,"sourceCodeEnd":1096,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/payload.py#L1060-L1096","documentation":"Raised by AsyncIterablePayload.decode when there are no cached chunks to decode. Because an async iterable is consumed lazily and can only be read once, decode() cannot materialize the content; the chunks must first be populated by awaiting as_bytes(), which caches them. Calling decode() before that has nothing to work with.","triggerScenarios":"Calling payload.decode() on an AsyncIterablePayload that has never been awaited via as_bytes(); calling decode() after the iterable was consumed directly (e.g. async for chunk in payload) without going through as_bytes().","commonSituations":"Inspecting/debugging a streaming payload's body; reusing a payload after partial consumption; code that worked for BytesPayload.decode() reused on a streaming payload.","solutions":["Await as_bytes() first to populate the cache, then call decode(): data = await payload.as_bytes(); text = payload.decode().","If you only need the string once, use text = (await payload.as_bytes()).decode('utf-8') directly.","Be aware that caching loads the entire body into memory; for large streams prefer incremental processing."],"exampleFix":"# before\ntext = payload.decode()\n\n# after\nawait payload.as_bytes()  # populates _cached_chunks\ntext = payload.decode()","handlingStrategy":"validation","validationCode":"if payload._cached_chunks is None:\n    await payload.as_bytes()\ntext = payload.decode()","typeGuard":"def payload_is_cached(payload) -> bool:\n    return getattr(payload, '_cached_chunks', None) is not None","tryCatchPattern":"try:\n    text = payload.decode()\nexcept TypeError:\n    await payload.as_bytes()\n    text = payload.decode()","preventionTips":["Always await as_bytes() before decode() on streaming payloads.","Prefer (await payload.as_bytes()).decode() for one-shot string access.","Do not consume the underlying iterable directly if you later need decode()."],"tags":["payload","async","streaming","api-misuse"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}