{"id":"c33e7c9ee40c8b14","repo":"aio-libs/aiohttp","slug":"called-begin-http-chunk-receiving-when-some-data-w","errorCode":null,"errorMessage":"Called begin_http_chunk_receiving when some data was already fed","messagePattern":"Called begin_http_chunk_receiving when some data was already fed","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/streams.py","lineNumber":308,"sourceCode":"\n        data_len = len(data)\n        self._size += data_len\n        self._buffer.append(data)\n        self.total_bytes += data_len\n\n        waiter = self._waiter\n        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","sourceCodeStart":290,"sourceCodeEnd":326,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/streams.py#L290-L326","documentation":"Internal guard in StreamReader.begin_http_chunk_receiving: HTTP chunked-transfer bookkeeping (_http_chunk_splits) is initialised only when no body bytes have been fed yet. If feed_data already delivered bytes and the parser then calls begin_http_chunk_receiving, aiohttp refuses rather than corrupt chunk offsets. This is almost always an aiohttp/parser-internal invariant violation, not user code.","triggerScenarios":"Triggered by the HTTP parser (http_parser.py:1015) calling payload.begin_http_chunk_receiving() after bytes were already fed without chunk framing — e.g. a response that changed framing mid-stream, a malformed server mixing Content-Length and chunked, or a buggy/proxy-injected payload. Reproducible mainly through malformed upstream traffic or a custom protocol feeding the StreamReader directly.","commonSituations":"Talking to a misbehaving proxy (e.g. nginx sub_filter rewriting bodies); receiving a response that started as Content-Length then switched to chunked; using a custom protocol object that mixes feed_data with chunk APIs; mismatch between parser version and streams.py after an in-tree edit.","solutions":["Capture the raw response (curl -i) to identify malformed Transfer-Encoding / Content-Length mixing on the server.","If using a custom protocol, do not call feed_data before begin_http_chunk_receiving — let the parser own framing.","Update aiohttp (and the vendored llhttp) in case it is a fixed parser bug.","File an aiohttp issue with the response bytes and headers if it reproduces against a real server."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"# Internal invariant — catch at the request boundary and surface as 502.\ntry:\n    resp = await session.get(url)\n    body = await resp.read()\nexcept RuntimeError as e:\n    if 'begin_http_chunk_receiving' in str(e):\n        raise BadGateway(f'upstream framing error: {e}') from e\n    raise","preventionTips":["Do not feed bytes to a StreamReader manually while using the chunk API.","Keep aiohttp and llhttp current to pick up parser fixes.","Capture full upstream bytes when this reproduces so you can file an issue."],"tags":["streams","http-parser","internal","chunked"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}