In Lib/asyncio/graph.py, _build_graph_for_future uses coro.cr_frame in the ag_await branch:
elif hasattr(coro, 'ag_await'):
st.append(FrameCallGraphEntry(coro.cr_frame))
coro = coro.ag_await
Async generators expose ag_frame, not cr_frame, so this raises AttributeError whenever the walk reaches it. The standard async for path routes through async_generator_asend objects which have neither attribute, so the walker hits the else: break first — which is why the test suite doesn't catch it. A coroutine whose cr_await chains directly to an async-generator-shaped object (duck-typed or manually driven) trips the bug.
Introduced in 1885988 (Jan 2025).
Linked PRs
In
Lib/asyncio/graph.py,_build_graph_for_futureusescoro.cr_framein theag_awaitbranch:Async generators expose
ag_frame, notcr_frame, so this raisesAttributeErrorwhenever the walk reaches it. The standardasync forpath routes throughasync_generator_asendobjects which have neither attribute, so the walker hits theelse: breakfirst — which is why the test suite doesn't catch it. A coroutine whosecr_awaitchains directly to an async-generator-shaped object (duck-typed or manually driven) trips the bug.Introduced in 1885988 (Jan 2025).
Linked PRs