You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<...>
resp_event_collector = helpers.ASGIResponseEventCollector()
if not _one_shot:
task_req = asyncio.create_task(
app(http_scope, req_event_emitter, resp_event_collector)
)
if _stream_result:
# NOTE(kgriffs): Wait until the response has been started and give
# the task a chance to progress. Otherwise, we won't have a
# status or headers to pass to StreamedResult.
while not resp_event_collector.status:
await asyncio.sleep(0)
return StreamedResult(
resp_event_collector.body_chunks,
code_to_http_status(resp_event_collector.status),
resp_event_collector.headers,
task_req,
req_event_emitter,
)
req_event_emitter.disconnect()
> await task_req
E RuntimeError: cannot reuse already awaited coroutine
task_req is created above using asyncio.create_task(...), and normally it can be awaited as many times as desired.
Printing it just before the failure gives:
<Task pending name='Task-3' coro=<App.__call__() running at /tmp/falcon/falcon/asgi/app.py:459> created at /usr/local/lib/python3.15/asyncio/tasks.py:395>
Interestingly, the error is only raised when running under PYTHONASYNCIODEBUG=1. Otherwise it passes just fine.
I was unable to isolate an independent MRE... Using Falcon's source tree @ falconry/falcon@6432f40, the following is enough to reproduce, given a venv using CPython dev version:
FALCON_DISABLE_CYTHON=1 pip install -e . pytest
# Works fine without asyncio debug: pytest tests/asgi/test_sse.py
PYTHONASYNCIODEBUG=1 pytest tests/asgi/test_sse.py
I ran a similar script under git bisect (first compiling the whole CPython source tree from scratch in a container), and bisected it down to this commit:
I'm not sure whether this is a bug in CPython, or just sloppy code on our end...
But I find the error itself, and the fact that it only happens under PYTHONASYNCIODEBUG=1, puzzling.
I've observed that changing the emitter to yield only once or to not sleep avoids the issue.
Maybe some task step interleaved with emitter() causes the failure.
Perhaps this could be helpful (this is right before the failing await):
Activity
[-]Puzzling "RuntimeError: cannot reuse already awaited coroutine" since 08bc03ff (under PYTHONASYNCIODEBUG)[/-][+]"RuntimeError: cannot reuse already awaited coroutine" since 08bc03ff (under PYTHONASYNCIODEBUG)[/+]johnslavik commentedon Jan 17, 2026
Smaller repro, still with Falcon:
I've observed that changing the emitter to yield only once or to not sleep avoids the issue.
Maybe some task step interleaved with
emitter()causes the failure.Perhaps this could be helpful (this is right before the failing
await):colesbury commentedon Jan 17, 2026
Thanks for the bug report. Is this using Cython and if so, is there a way to run it without Cython?
colesbury commentedon Jan 17, 2026
Never mind -- I understand the bug now and will have a fix shortly.
pythongh-143939: Fix assignment to _PyThreadStateImpl.generator_retur…
gh-143939: Fix assignment to `_PyThreadStateImpl.generator_return_kin…
colesbury commentedon Jan 20, 2026
This is fixed in main now. Thanks again for the bug report!
pythongh-143939: Fix assignment to `_PyThreadStateImpl.generator_retu…