aio-libs/aiohttp · error · RuntimeError
Called while some coroutine is waiting for incoming data.
Error message
Called while some coroutine is waiting for incoming data.
What it means
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.
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.
Example fix
# before
asyncio.create_task(consume_async(stream))
rest = stream.read_nowait() # raises
# after
# either consume fully async, or ensure no pending waiter first:
if stream._waiter is None or stream._waiter.done():
rest = stream.read_nowait() Defensive patterns
Strategy: validation
Validate before calling
w = stream._waiter
if w is not None and not w.done():
raise RuntimeError('cannot read_nowait while async read pending')
rest = stream.read_nowait() Type guard
def safe_to_read_nowait(stream) -> bool:
w = getattr(stream, '_waiter', None)
return w is None or w.done() Try / catch
try:
rest = stream.read_nowait()
except RuntimeError as e:
if 'waiting for incoming data' in str(e):
rest = b''
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Timeout handlers that try to flush remaining data; custom protocols mixing sync and async reads; debugging code that dumps the buffer mid-read.
Related errors
- () called while another coroutine is already waiting for…
- EmptyStreamReader._on_chunk_received is read-only
- Cannot call .write() for websocket
- Concurrent call to receive() is not allowed
- Concurrent call to receive() is not allowed
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/46bcf1a0ad71e614.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/streams.py:532
block = await self.read(n)
if not block:
partial = b"".join(blocks)
raise asyncio.IncompleteReadError(partial, len(partial) + n)
blocks.append(block)
n -= len(block)
return b"".join(blocks)
def read_nowait(self, n: int = -1) -> bytes:
# default was changed to be consistent with .read(-1)
#
# I believe the most users don't know about the method and
# they are not affected.
if self._exception is not None:
raise self._exception
if self._waiter and not self._waiter.done():
raise RuntimeError(
"Called while some coroutine is waiting for incoming data."
)
chunk = self._read_nowait(n)
if chunk and (cb := self._on_chunk_received) is not None:
# read_nowait is sync but the hook is async; schedule it so the
# observability event still fires.
# TODO: Save and await this task.
asyncio.create_task(cb(chunk)) # type: ignore[unused-awaitable]
return chunk
def _read_nowait_chunk(self, n: int) -> bytes:
first_buffer = self._buffer[0]
offset = self._buffer_offset
if n != -1 and len(first_buffer) - offset > n:
data = first_buffer[offset : offset + n]
self._buffer_offset += n
View on GitHub (pinned to d041d4d0fd)