{"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/c0ef574e29109210e96e652771ae4e7b88615fa4/aiohttp/streams.py#L514-L550","documentation":"Raised by StreamReader.read_nowait when an async reader is currently blocked in _wait (self._waiter is pending). read_nowait is a synchronous drain that bypasses the waiter protocol; calling it concurrently with an awaited read would steal the awaited data. aiohttp refuses with RuntimeError to preserve the read-coroutine contract.","triggerScenarios":"Calling request.content.read_nowait() from sync code (e.g. a sync callback, __del__, signal handler) while an async task is awaiting request.content.read(...); mixing read_nowait with awaited reads for performance without coordination.","commonSituations":"Sync middleware/callback that peeks at the buffer while the handler is reading; instrumentation that drains for metrics; incorrect port of a sync API onto an async stream.","solutions":["Do not mix read_nowait with awaited reads on the same stream — pick one consumer model.","Before read_nowait, check `if request.content._waiter and not request.content._waiter.done(): ...` (or just avoid read_nowait).","Use readany() (async) instead of read_nowait for non-blocking-style reads.","Ensure no background await is in flight when you call read_nowait."],"exampleFix":"// before\n# in a sync callback, while handler awaits request.read():\npeek = request.content.read_nowait()  # RuntimeError\n// after\n# schedule the peek as async instead:\npeek = await request.content.readany()","handlingStrategy":"validation","validationCode":"def safe_read_nowait(stream, n=-1):\n    waiter = getattr(stream, '_waiter', None)\n    if waiter is not None and not waiter.done():\n        raise RuntimeError('cannot read_nowait while async read is pending')\n    return stream.read_nowait(n)","typeGuard":null,"tryCatchPattern":"try:\n    chunk = stream.read_nowait()\nexcept RuntimeError as e:\n    if 'waiting for incoming data' in str(e):\n        # fall back to async read\n        chunk = await stream.readany()\n    else:\n        raise","preventionTips":["Never mix sync read_nowait with awaited reads on the same stream.","Use readany() for non-blocking-style reads.","Centralize all stream access behind one async consumer."],"tags":["streams","concurrency","sync-mixing"],"analyzedSha":"c0ef574e29109210e96e652771ae4e7b88615fa4","analyzedAt":"2026-08-04T19:51:05.467Z","schemaVersion":2}