This rule raises when a control flow statement (return, break, continue) is used inside a TaskGroup or
Nursery context manager.
Using control flow statements like return, break, or continue inside async TaskGroup or Nursery blocks leads
to counterintuitive behavior that can confuse developers and introduce bugs.
In asyncio’s TaskGroup, control flow statements don’t take immediate effect. Instead, they wait for all tasks in the group to complete before executing. This can lead to:
In Trio and AnyIO nurseries, return values can be lost if other tasks in the nursery raise exceptions:
Move the control flow statement outside the TaskGroup or Nursery block, and use the appropriate cancellation mechanism before exiting the block.
import asyncio
async def process():
async with asyncio.TaskGroup() as tg:
tg.create_task(background_task())
if condition():
return "result" # Noncompliant: waits for background_task() to complete
import asyncio
async def process():
result = None
async with asyncio.TaskGroup() as tg:
task = tg.create_task(background_task())
if condition():
result = "result"
task.cancel()
return result
Move the control flow statement outside the Nursery block, and use the appropriate cancellation mechanism before exiting the block.
import trio
async def process():
async with trio.open_nursery() as nursery:
nursery.start_soon(background_task)
if condition():
return "result" # Noncompliant: value may be lost
import trio
async def process():
result = None
async with trio.open_nursery() as nursery:
nursery.start_soon(background_task)
if condition():
result = "result"
nursery.cancel_scope.cancel()
return result
Move the control flow statement outside the TaskGroup block, and use the appropriate cancellation mechanism before exiting the block.
import anyio
async def process():
async with anyio.create_task_group() as tg:
tg.start_soon(background_task)
if condition():
return "result" # Noncompliant: waits for background_task
import anyio
async def process():
result = None
async with anyio.create_task_group() as tg:
tg.start_soon(background_task)
if condition():
result = "result"
tg.cancel_scope.cancel()
return result