This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: fastapi-anyio-taskgroup-cancellation-isolation

FastAPI AnyIO TaskGroup Structured Concurrency & Cancellation Isolation

Enforces deterministic teardown and structured concurrency isolation for AnyIO task groups within FastAPI route handlers when client disconnects occur. Mandates explicit cancellation shielding for non-idempotent operations and prevents AnyIO cancellation exceptions from corrupting shared worker thread pools or leaking raw errors into ASGI middleware.

Prohibited Anti-Pattern: Spawning detached asyncio tasks or unshielded AnyIO TaskGroups that leak unhandled cancellation exceptions and leave thread-pool workers orphaned on client disconnect

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FastAPI AnyIO TaskGroup Structured Concurrency & Cancellation Isolation - Enforces deterministic teardown and structured concurrency isolation for AnyIO task groups within FastAPI route handlers when client disconnects occur. Mandates explicit cancellation shielding for non-idempotent operations and prevents AnyIO cancellation exceptions from corrupting shared worker thread pools or leaking raw errors into ASGI middleware.
globs: **/routes/**/*.py, **/api/**/*.py, **/endpoints/**/*.py, **/services/**/*.py
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/fastapi-anyio-taskgroup-cancellation-isolation"
---

# FastAPI AnyIO TaskGroup Structured Concurrency & Cancellation Isolation

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Spawning detached asyncio tasks or unshielded AnyIO TaskGroups that leak unhandled cancellation exceptions and leave thread-pool workers orphaned on client disconnect

## System Constraints
You are a Principal Software Architect enforcing production-grade structured concurrency standards in FastAPI applications backed by AnyIO. You mandate deterministic task teardown on HTTP client disconnects, strict cancellation shielding for atomic operations, and rigorous isolation between ASGI request loops and thread-pool executors.

## Strict Guidelines
- Engineers MUST ALWAYS scope concurrent async operations within an `anyio.create_task_group()` context block instead of spawning unmanaged `asyncio.create_task()` fire-and-forget coroutines.
- Engineers MUST wrap non-interruptible side-effects, resource cleanups, or audit commits inside `anyio.CancelScope(shield=True)` to prevent torn states when a client aborts the connection.
- Engineers MUST NOT allow `anyio.get_cancelled_exc_class()` or `asyncio.CancelledError` to propagate unhandled out of endpoints as 500 Internal Server Errors; graceful abort logging or clean HTTP 499 handling MUST be applied.
- Code MUST pass `abandon_on_cancel=False` (or use bounded cancellation tokens) when dispatching blocking I/O via `anyio.to_thread.run_sync` to avoid thread exhaustion and orphaned connection checkouts.
- Services MUST ensure that sub-tasks scheduled in a task group handle cancellation cooperatively through explicit checkpoints or non-blocking async primitives.
- Components NEVER catch naked `Exception` blocks around TaskGroups without re-raising `anyio.get_cancelled_exc_class()` or extracting sub-exceptions from `ExceptionGroup` / `anyio.ExceptionGroup`.

## Bad vs Good Implementations
### Structured Concurrency and Cancellation Isolation in FastAPI Route

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Using asyncio.create_task decouples lifecycle management from the ASGI request scope, risking orphan execution or silent failures. Catching bare Exception and converting to 500 swallows asyncio.CancelledError or bubbles up inappropriately. Thread dispatches via asyncio.to_thread cannot be tracked or shielded cleanly on premature disconnect.
```python
import asyncio
from fastapi import APIRouter, Depends, HTTPException
from services.billing import process_payment
from services.telemetry import log_metric

router = APIRouter()

@router.post("/checkout")
async def checkout(order_id: str):
    try:
        # ANTI-PATTERN: Detached task spawns leak on disconnect.
        # If client disconnects, process_payment may be severed halfway or run unbounded,
        # and log_metric may never execute. Raw CancelledError crashes middleware.
        asyncio.create_task(log_metric("checkout_initiated", order_id))
        
        # Unstructured thread dispatch without cancellation isolation
        result = await asyncio.to_thread(process_payment, order_id)
        return {"status": "completed", "result": result}
    except Exception as exc:
        # Swallows cancellation or emits 500 on client disconnect
        raise HTTPException(status_code=500, detail=str(exc))
```

#### Production Standard (Correct)
> **Standard**: Uses anyio.create_task_group for deterministic lifecycle binding. Blocking calls use anyio.to_thread.run_sync(abandon_on_cancel=False) to prevent pool corruption. If the client disconnects, the cancellation exception is explicitly caught and isolated; critical rollback/audit operations are safely executed under anyio.CancelScope(shield=True).
```python
import anyio
from fastapi import APIRouter, Request, status
from fastapi.responses import JSONResponse
from services.billing import process_payment_sync
from services.telemetry import emit_audit_event

router = APIRouter()

@router.post("/checkout")
async def checkout(request: Request, order_id: str):
    cancelled_exc = anyio.get_cancelled_exc_class()
    try:
        async with anyio.create_task_group() as tg:
            # Spawn cooperative telemetry within structured scope
            tg.start_soon(emit_audit_event, "checkout_initiated", order_id)
            
            # Execute sync work with cancellation awareness in managed thread pool
            # abandon_on_cancel=False guarantees the thread finishes safely before context exit
            result = await anyio.to_thread.run_sync(
                process_payment_sync, order_id, abandon_on_cancel=False
            )
            return {"status": "completed", "result": result}
    except cancelled_exc:
        # Handle client disconnect gracefully without leaking unhandled exceptions
        with anyio.CancelScope(shield=True):
            # Shield critical cleanup and compensation logic from cancellation
            await emit_audit_event("checkout_aborted_by_client", order_id)
        return JSONResponse(
            status_code=499, # Client Closed Request
            content={"status": "aborted", "detail": "Client disconnected before completion"}
        )
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: FastAPI AnyIO TaskGroup Structured Concurrency & Cancellation Isolation

FastAPI AnyIO TaskGroup Structured Concurrency & Cancellation Isolation defines an industrial-grade behavioral standard for backend engineering. Enforces deterministic teardown and structured concurrency isolation for AnyIO task groups within FastAPI route handlers when client disconnects occur. Mandates explicit cancellation shielding for non-idempotent operations and prevents AnyIO cancellation exceptions from corrupting shared worker thread pools or leaking raw errors into ASGI middleware. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Spawning detached asyncio tasks or unshielded AnyIO TaskGroups that leak unhandled cancellation exceptions and leave thread-pool workers orphaned on client disconnect Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftSpawning detached asyncio tasks or unshielded AnyIO TaskGroups that leak unhandled cancellation exceptions and leave thread-pool workers orphaned on client disconnectCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS scope concurrent async operations within an `anyio.create_task_group()` context block instead of spawning unmanaged `asyncio.create_task()` fire-and-forget coroutines.

Engineers MUST ALWAYS scope concurrent async operations within an `anyio.create_task_group()` context block instead of spawning unmanaged `asyncio.create_task()` fire-and-forget coroutines.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST wrap non-interruptible side-effects, resource cleanups, or audit commits inside `anyio.CancelScope(shield=True)` to prevent torn states when a client aborts the connection.

Engineers MUST wrap non-interruptible side-effects, resource cleanups, or audit commits inside `anyio.CancelScope(shield=True)` to prevent torn states when a client aborts the connection.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Engineers MUST NOT allow `anyio.get_cancelled_exc_class()` or `asyncio.CancelledError` to propagate unhandled out of endpoints as 500 Internal Server Errors

Engineers MUST NOT allow `anyio.get_cancelled_exc_class()` or `asyncio.CancelledError` to propagate unhandled out of endpoints as 500 Internal Server Errors; graceful abort logging or clean HTTP 499 handling MUST be applied.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Code MUST pass `abandon_on_cancel=False` (or use bounded cancellation tokens) when dispatching blocking I/O via `anyio.to_thread.run_sync` to avoid thread exhaustion and orphaned connection checkouts.

Code MUST pass `abandon_on_cancel=False` (or use bounded cancellation tokens) when dispatching blocking I/O via `anyio.to_thread.run_sync` to avoid thread exhaustion and orphaned connection checkouts.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Services MUST ensure that sub-tasks scheduled in a task group handle cancellation cooperatively through explicit checkpoints or non-blocking async primitives.

Services MUST ensure that sub-tasks scheduled in a task group handle cancellation cooperatively through explicit checkpoints or non-blocking async primitives.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Components NEVER catch naked `Exception` blocks around TaskGroups without re-raising `anyio.get_cancelled_exc_class()` or extracting sub-exceptions from `ExceptionGroup` / `anyio.ExceptionGroup`.

Components NEVER catch naked `Exception` blocks around TaskGroups without re-raising `anyio.get_cancelled_exc_class()` or extracting sub-exceptions from `ExceptionGroup` / `anyio.ExceptionGroup`.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is FastAPI AnyIO TaskGroup Structured Concurrency & Cancellation Isolation critical for AI coding assistants?

Enforces deterministic teardown and structured concurrency isolation for AnyIO task groups within FastAPI route handlers when client disconnects occur. Mandates explicit cancellation shielding for non-idempotent operations and prevents AnyIO cancellation exceptions from corrupting shared worker thread pools or leaking raw errors into ASGI middleware. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Spawning detached asyncio tasks or unshielded AnyIO TaskGroups that leak unhandled cancellation exceptions and leave thread-pool workers orphaned on client disconnect) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

FastAPI