{"record":{"id":"46bcf1a0ad71e614","repo":"aio-libs/aiohttp","slug":"called-while-some-coroutine-is-waiting-for-incomin","errorCode":null,"errorMessage":"Called while some coroutine is waiting for incoming data.","messagePattern":"Called while some coroutine is waiting for incoming data\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"aiohttp/streams.py","lineNumber":532,"sourceCode":"            block = await self.read(n)\n            if not block:\n                partial = b\"\".join(blocks)\n                raise asyncio.IncompleteReadError(partial, len(partial) + n)\n            blocks.append(block)\n            n -= len(block)\n\n        return b\"\".join(blocks)\n\n    def read_nowait(self, n: int = -1) -> bytes:\n        # default was changed to be consistent with .read(-1)\n        #\n        # I believe the most users don't know about the method and\n        # they are not affected.\n        if self._exception is not None:\n            raise self._exception\n\n        if self._waiter and not self._waiter.done():\n            raise RuntimeError(\n                \"Called while some coroutine is waiting for incoming data.\"\n            )\n\n        chunk = self._read_nowait(n)\n        if chunk and (cb := self._on_chunk_received) is not None:\n            # read_nowait is sync but the hook is async; schedule it so the\n            # observability event still fires.\n            # TODO: Save and await this task.\n            asyncio.create_task(cb(chunk))  # type: ignore[unused-awaitable]\n        return chunk\n\n    def _read_nowait_chunk(self, n: int) -> bytes:\n        first_buffer = self._buffer[0]\n        offset = self._buffer_offset\n        if n != -1 and len(first_buffer) - offset > n:\n            data = first_buffer[offset : offset + n]\n            self._buffer_offset += n\n","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/streams.py#L514-L550","documentation":"Raised by StreamReader.read_nowait when self._waiter exists and is not done, i.e. another coroutine is currently blocked in an async read (read/readline/readuntil) on the same reader. read_nowait is a synchronous drain of whatever is already buffered; calling it while a reader is suspended would steal its data and corrupt the read protocol.","triggerScenarios":"Mixing await stream.read(n) (async) and stream.read_nowait() (sync) on the same reader concurrently; a cancellation/timeout leaving a _waiter pending and then calling read_nowait; a background task calling read_nowait while the main task reads.","commonSituations":"Timeout handlers that try to flush remaining data; custom protocols mixing sync and async reads; debugging code that dumps the buffer mid-read.","solutions":["Do not mix read_nowait with async reads on the same stream; pick one consumption style.","Ensure no async read is in flight before calling read_nowait (check stream._waiter is None or done).","On timeout, cancel the pending read task fully before draining."],"exampleFix":"# before\nasyncio.create_task(consume_async(stream))\nrest = stream.read_nowait()  # raises\n\n# after\n# either consume fully async, or ensure no pending waiter first:\nif stream._waiter is None or stream._waiter.done():\n    rest = stream.read_nowait()","handlingStrategy":"validation","validationCode":"w = stream._waiter\nif w is not None and not w.done():\n    raise RuntimeError('cannot read_nowait while async read pending')\nrest = stream.read_nowait()","typeGuard":"def safe_to_read_nowait(stream) -> bool:\n    w = getattr(stream, '_waiter', None)\n    return w is None or w.done()","tryCatchPattern":"try:\n    rest = stream.read_nowait()\nexcept RuntimeError as e:\n    if 'waiting for incoming data' in str(e):\n        rest = b''\n    else:\n        raise","preventionTips":["Pick either async reads or read_nowait for a given stream; do not mix.","Fully cancel pending read tasks on timeout before draining.","Check _waiter is None/done before calling read_nowait."],"tags":["streams","concurrency","sync","api-misuse"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}