{"id":"4680424f6f4596ba","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 {expected} bytes).","messagePattern":"Not enough data to satisfy content length header \\(received (.+?) of (.+?) bytes\\)\\.","errorType":"http","errorClass":"ContentLengthError","httpStatus":400,"severity":"error","filePath":"aiohttp/http_parser.py","lineNumber":918,"sourceCode":"        self.payload = real_payload\n\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            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        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\";\"\n    ) -> tuple[PayloadState, bytes]:\n        \"\"\"Receive a chunk of data to process.\n\n        Return:\n            PayloadState - The current state of payload processing.\n                           This function may be called with empty bytes after returning\n                           PAYLOAD_HAS_PENDING_INPUT to continue processing after a pause.\n            bytes - If payload is complete, this is the unconsumed bytes intended for the","sourceCodeStart":900,"sourceCodeEnd":936,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/http_parser.py#L900-L936","documentation":"ContentLengthError raised in HttpPayloadParser.feed_eof when the connection closes while the body is being read in PARSE_LENGTH mode and fewer than Content-Length bytes arrived. The message reports received vs expected bytes.","triggerScenarios":"Server declared Content-Length: N but the socket closed after delivering < N bytes. feed_eof() in the PARSE_LENGTH branch computes `received = _length_expected - _length` and raises ContentLengthError.","commonSituations":"Truncated responses from a reverse proxy that times out mid-body; upstream connection drop; Content-Length computed wrong (head vs body mismatch); keep-alive closed early; compression applied without recomputing Content-Length.","solutions":["Verify the server's Content-Length matches the actual body size (capture with curl -i).","Check for proxies/CDNs truncating large responses or applying compression that changes body size.","Retry the request; if reproducible, report to the server owner.","Handle ContentLengthError and fall back to a streaming/transfer-encoding read."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from aiohttp.http_exceptions import ContentLengthError\ntry:\n    body = await resp.read()\nexcept ContentLengthError:\n    # truncated body — retry or stream\n    ...","preventionTips":["Treat ContentLengthError as a transport-level truncation, not an app error.","Use streaming reads to detect truncation early on large downloads."],"tags":["http","parser","payload","content-length","truncated"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}