python/cpython · error · RuntimeError
{func_name}() called while another coroutine is already wait
Error message
{func_name}() called while another coroutine is already waiting for incoming data What it means
RuntimeError raised by StreamReader._wait_for_data when a second read coroutine starts while another is already suspended waiting for feed_data(). The reader uses a single _waiter future to link protocol callbacks to one read call, so two concurrent readers cannot be told apart and the state is rejected rather than silently corrupted.
Source
Thrown at Lib/asyncio/streams.py:528
except NotImplementedError:
# The transport can't be paused.
# We'll just have to buffer all data.
# Forget the transport so we don't keep trying.
self._transport = None
else:
self._paused = True
async def _wait_for_data(self, func_name):
"""Wait until feed_data() or feed_eof() is called.
If stream was paused, automatically resume it.
"""
# StreamReader uses a future to link the protocol feed_data() method
# to a read coroutine. Running two read coroutines at the same time
# would have an unexpected behaviour. It would not possible to know
# which coroutine would get the next data.
if self._waiter is not None:
raise RuntimeError(
f'{func_name}() called while another coroutine is '
f'already waiting for incoming data')
assert not self._eof, '_wait_for_data after EOF'
# Waiting for data while paused will make deadlock, so prevent it.
# This is essential for readexactly(n) for case when n > self._limit.
if self._paused:
self._paused = False
self._transport.resume_reading()
self._waiter = self._loop.create_future()
try:
await self._waiter
finally:
self._waiter = None
async def readline(self):View on GitHub (pinned to bc6749cc3b)
Solutions
- Ensure exactly one consumer coroutine per StreamReader; route all reads through that consumer (queue or dedicated reader task)
- Wrap reads in an asyncio.Lock if multiple tasks must read, so only one is inside a read call at a time
- For wait_for timeouts, cancel and await the inner read fully before retrying, rather than starting a parallel read
- Split the stream (e.g. tee via a queue fed by one reader) when several tasks need the data
Example fix
// before
async def worker(r):
line = await r.readline() # two workers share r -> RuntimeError
// after
read_lock = asyncio.Lock()
async def worker(r):
async with read_lock:
line = await r.readline() Defensive patterns
Strategy: validation
Validate before calling
class SingleStreamReader:
def __init__(self, reader: asyncio.StreamReader):
self.reader = reader
self._lock = asyncio.Lock()
async def readline(self):
async with self._lock:
return await self.reader.readline() Type guard
null
Try / catch
null
Prevention
- Enforce one consumer task per StreamReader in code review; make the owner explicit in design
- Route all reads through a single accessor that holds an asyncio.Lock
- Avoid wait_for around reads while another read of the same stream can be in flight
When it happens
Trigger: Two coroutines simultaneously call any of read(), readline(), readuntil(), readexactly(), or read(-1) on the same StreamReader while data is not yet available so both reach the waiting state; e.g. a timeout wrapper that spawns read() while an outer read() is still pending, or one task reading stdout while another reads it too.
Common situations: asyncio.wait_for(reader.readline(), ...) combined with a separately scheduled read task; multiple consumers 'sharing' a connection; a heartbeat task that reads occasionally while the main loop also reads; refactors that moved reads into a helper launched with create_task.
Related errors
- d3-flame-graph library failed to load
- unable to write; sendfile is in progress
- unable to writelines; sendfile is in progress
- Empty waiter is already set
- staggered race failed
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/84e26d8261ecf971.
Report an issue: GitHub.