{"id":"da8d8596a7f8a0a0","repo":"aio-libs/aiohttp","slug":"called-end-chunk-receiving-without-calling-begin-c","errorCode":null,"errorMessage":"Called end_chunk_receiving without calling begin_chunk_receiving first","messagePattern":"Called end_chunk_receiving without calling begin_chunk_receiving first","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/streams.py","lineNumber":315,"sourceCode":"        if waiter is not None:\n            self._waiter = None\n            set_result(waiter, None)\n\n        if self._size > self._high_water:\n            self._protocol.pause_reading()\n        return False\n\n    def begin_http_chunk_receiving(self) -> None:\n        if self._http_chunk_splits is None:\n            if self.total_bytes:\n                raise RuntimeError(\n                    \"Called begin_http_chunk_receiving when some data was already fed\"\n                )\n            self._http_chunk_splits = collections.deque()\n\n    def end_http_chunk_receiving(self) -> None:\n        if self._http_chunk_splits is None:\n            raise RuntimeError(\n                \"Called end_chunk_receiving without calling \"\n                \"begin_chunk_receiving first\"\n            )\n\n        # self._http_chunk_splits contains logical byte offsets from start of\n        # the body transfer. Each offset is the offset of the end of a chunk.\n        # \"Logical\" means bytes, accessible for a user.\n        # If no chunks containing logical data were received, current position\n        # is difinitely zero.\n        pos = self._http_chunk_splits[-1] if self._http_chunk_splits else 0\n\n        if self.total_bytes == pos:\n            # We should not add empty chunks here. So we check for that.\n            # Note, when chunked + gzip is used, we can receive a chunk\n            # of compressed data, but that data may not be enough for gzip FSM\n            # to yield any uncompressed data. That's why current position may\n            # not change after receiving a chunk.\n            return","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/streams.py#L297-L333","documentation":"Internal guard in StreamReader.end_http_chunk_receiving: it requires _http_chunk_splits to be non-None, i.e. begin_http_chunk_receiving was called first. Calling end without begin indicates a parser-state mismatch — the parser emitted a chunk-end marker with no matching begin. Like 185, this is an aiohttp-internal invariant rather than something typical application code triggers.","triggerScenarios":"The HTTP parser (http_parser.py:1045) calls payload.end_http_chunk_receiving() while _http_chunk_splits is None — e.g. malformed chunked body missing the chunk-size line, or a custom protocol object that calls end_http_chunk_receiving without first calling begin_http_chunk_receiving.","commonSituations":"Malformed upstream chunked body (server bug); a man-in-the-middle truncating chunk framing; a custom request/response feeding path that mishandles the chunk API; race between parser version and streams internals.","solutions":["Inspect raw upstream bytes to confirm chunk framing is well-formed (size CRLF data CRLF ...).","Avoid calling the chunk API manually — delegate to the HTTP parser.","Upgrade aiohttp/llhttp; if it reproduces, file an issue with full response capture.","For custom StreamReader feeding, always bracket with begin/end and never call end twice."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    body = await resp.read()\nexcept RuntimeError as e:\n    if 'end_chunk_receiving' in str(e):\n        log.warning('upstream chunk framing mismatch on %s', url)\n        raise BadGateway('malformed chunked response') from e\n    raise","preventionTips":["Never pair begin_http_chunk_receiving/end_http_chunk_receiving incorrectly in custom protocols.","Let the HTTP parser own chunk framing.","Capture raw bytes when reproducing for upstream bug reports."],"tags":["streams","http-parser","internal","chunked"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}