Describe the Bug
If two sibling async fields run together and one raises, on_operation can exit before the other field has finished.
This makes on_operation unsafe as a strict "request is fully done" boundary for closing shared async resources.
System Information
- Operating system: macOS 15.4
- Python version: 3.14.0
- Strawberry version (if applicable): 0.312.0
Additional Context
Minimal demonstration is below.
Observed order:
operation enter
slow start
boom raise
operation exit
execute returned
slow finish
So on_operation exited before all field work was done.
Code:
import asyncio
import logging
import strawberry
from strawberry.extensions import SchemaExtension
timeline: list[str] = []
slow_started = asyncio.Event()
class ProbeExtension(SchemaExtension):
async def on_operation(self):
timeline.append("operation enter")
try:
yield
finally:
timeline.append("operation exit")
@strawberry.type
class Query:
@strawberry.field
async def slow(self) -> str:
timeline.append("slow start")
slow_started.set()
await asyncio.sleep(0.05)
timeline.append("slow finish")
return "slow"
@strawberry.field
async def boom(self) -> str:
await slow_started.wait()
timeline.append("boom raise")
raise RuntimeError("boom")
schema = strawberry.Schema(query=Query, extensions=[ProbeExtension])
async def run_demo() -> None:
logging.getLogger("strawberry.execution").setLevel(logging.CRITICAL)
result = await schema.execute("{ slow boom }")
timeline.append("execute returned")
# Let the still-running sibling resolver finish so the ordering is visible.
await asyncio.sleep(0.1)
timeline.append("after extra sleep")
print("GraphQL errors:", [error.message for error in result.errors or []])
print()
print("Timeline:")
for entry in timeline:
print(entry)
operation_exit_idx = timeline.index("operation exit")
slow_finish_idx = timeline.index("slow finish")
assert operation_exit_idx < slow_finish_idx, timeline
print()
print("Observed: `on_operation` exited before `slow` finished.")
def main() -> None:
asyncio.run(run_demo())
if __name__ == "__main__":
main()
Describe the Bug
If two sibling async fields run together and one raises, on_operation can exit before the other field has finished.
This makes on_operation unsafe as a strict "request is fully done" boundary for closing shared async resources.
System Information
Additional Context
Minimal demonstration is below.
Observed order:
Code: