{"record":{"id":"118473f5c82745c0","repo":"aio-libs/aiohttp","slug":"not-enough-data-to-satisfy-content-length-header","errorCode":null,"errorMessage":"Not enough data to satisfy content length header (received {received} of {self._length_expected} bytes).","messagePattern":"Not enough data to satisfy content length header \\(received (.+?) of (.+?) bytes\\)\\.","errorType":"exception","errorClass":"ContentLengthError","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":921,"sourceCode":"\n    def pause_reading(self) -> None:\n        self._paused = True\n\n    def feed_eof(self) -> None:\n        if self._type == ParseState.PARSE_UNTIL_EOF:\n            self._eof_pending = True\n            while self._more_data_available:\n                if self._paused:\n                    self._paused = False\n                    return  # Will resume via feed_data(b\"\") later\n                self._more_data_available = self.payload.feed_data(b\"\")\n            self.payload.feed_eof()\n            self.done = True\n            self._eof_pending = False\n        elif self._type == ParseState.PARSE_LENGTH:\n            if self._length:\n                received = self._length_expected - self._length\n                raise ContentLengthError(\n                    f\"Not enough data to satisfy content length header \"\n                    f\"(received {received} of {self._length_expected} bytes).\"\n                )\n            # Body has already been received, but parser paused.\n            while self._more_data_available:\n                if self._paused:\n                    self._paused = False\n                    return  # Will resume via feed_data(b\"\") later\n                self._more_data_available = self.payload.feed_data(b\"\")\n            self.payload.feed_eof()\n            self.done = True\n        elif self._type == ParseState.PARSE_CHUNKED:\n            raise TransferEncodingError(\n                \"Not enough data to satisfy transfer length header.\"\n            )\n\n    def feed_data(\n        self, chunk: bytes, SEP: _SEP = b\"\\r\\n\", CHUNK_EXT: bytes = b\";\"","sourceCodeStart":903,"sourceCodeEnd":939,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/http_parser.py#L903-L939","documentation":"Raised as ContentLengthError (a BadHttpMessage subclass) when the connection reaches EOF but fewer body bytes were received than declared by Content-Length. HttpPayloadParser.feed_eof, in the PARSE_LENGTH branch, checks if self._length is still positive (bytes still owed); if so it raises with the received vs expected counts. This indicates a truncated message body.","triggerScenarios":"A response/request has a Content-Length: N header, but the stream closes (feed_eof) before N body bytes arrive. Fires when _type == ParseState.PARSE_LENGTH and self._length > 0 at EOF.","commonSituations":"The server (or client) closes the connection mid-body before sending all Content-Length bytes; a proxy truncating the response; network resets/instability dropping the tail; a server that sets Content-Length but then errors out sending fewer bytes; chunked encoding incorrectly absent; a buggy upstream that miscomputes Content-Length.","solutions":["If you are the sender, ensure you write exactly Content-Length body bytes before closing.","On the receiving side, treat this as a connection-level error and retry the request idempotently.","Verify no intermediary (proxy, firewall) is truncating large responses.","If the body length is genuinely unknown, use chunked transfer-encoding instead of Content-Length.","Check server logs for exceptions during response streaming."],"exampleFix":"# before (server computes Content-Length wrong)\r\nreturn web.Response(body=data, headers={'Content-Length': str(len(data) + 10)})\r\n\r\n# after (let aiohttp set Content-Length, or use chunked)\r\nreturn web.Response(body=data)  # Content-Length auto-set correctly","handlingStrategy":"retry","validationCode":"async def safe_read(resp) -> bytes:\n    try:\n        return await resp.read()\n    except Exception:\n        # ContentLengthError indicates truncation; caller decides on retry\n        raise","typeGuard":null,"tryCatchPattern":"from aiohttp.http_exceptions import ContentLengthError\nimport aiohttp\n\nasync def fetch_full(url, *, attempts=3):\n    last = None\n    for i in range(attempts):\n        try:\n            async with aiohttp.ClientSession() as s:\n                async with s.get(url) as r:\n                    return await r.read()\n        except ContentLengthError as e:\n            last = e\n            await asyncio.sleep(2 ** i)\n    raise last\n","preventionTips":["Retry idempotent requests on truncation errors.","Verify servers compute Content-Length correctly (or omit it / use chunked).","Check intermediaries for response truncation on large payloads.","Use chunked encoding when body length is uncertain."],"tags":["http-parser","content-length","payload","truncated","body"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}