This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: axum-08-cancellation-safe-streaming-pipeline-standard

Axum 0.8 Cancellation-Safe Streaming Pipeline Standard

Axum request futures are dropped immediately at the nearest yield point when a client terminates the connection. Streaming upload pipelines must bind all intermediate resources to deterministic RAII rollback guards to eliminate orphaned temporary files and leaked file descriptors upon mid-stream aborts.

Prohibited Anti-Pattern: Orphaned Partial Files and Leaked File Descriptors via Naked Async File Writes During Premature Client Disconnection

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Axum 0.8 Cancellation-Safe Streaming Pipeline Standard - Axum request futures are dropped immediately at the nearest yield point when a client terminates the connection. Streaming upload pipelines must bind all intermediate resources to deterministic RAII rollback guards to eliminate orphaned temporary files and leaked file descriptors upon mid-stream aborts.
globs: src/**/*.rs, crates/**/*.rs
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/axum-08-cancellation-safe-streaming-pipeline-standard"
---

# Axum 0.8 Cancellation-Safe Streaming Pipeline Standard

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Orphaned Partial Files and Leaked File Descriptors via Naked Async File Writes During Premature Client Disconnection

## System Constraints
You are a Principal Rust Architect enforcing Axum 0.8 Cancellation-Safe Streaming Pipeline Standards. In Axum and Tokio, cancellation occurs synchronously via Future drops at `.await` yield points. You must strictly mandate that all streaming ingestion pipelines, file I/O operations, and scratchpad resources are bound to deterministic RAII cleanup handles that purge uncommitted state if dropped before reaching a validated completion invariant.

## Strict Guidelines
- Engineers MUST ALWAYS encapsulate streaming file sinks in RAII transaction guards (e.g., custom cleanup wrappers or `tempfile::NamedTempFile`) that automatically remove incomplete artifacts on drop unless explicitly committed.
- Engineers MUST NOT rely on sequential post-loop cleanup code in streaming handlers, as client drops cause immediate future termination at `.await` boundaries, skipping all downstream logic.
- Code MUST handle `axum::body::Body` consumption through bounded stream chunk adapters and forward-propagate cancellation without spawning detached background write tasks.
- Services MUST flush and sync file descriptors synchronously or via explicit blocking offload prior to renaming/promoting temporary storage to persistent object stores.
- Components NEVER use naked `tokio::fs::File::create` with hardcoded paths directly inside streaming request loops without guaranteed unlink-on-drop mechanics.

## Bad vs Good Implementations
### Cancellation-Vulnerable Streaming Upload vs RAII Transactional Cleanup

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: In Axum, when the downstream HTTP client disconnects, the top-level handler future is dropped at the nearest `.await` point inside the loop. The file is left partially written on disk with no cleanup routine executed, rapidly leaking disk space and inodes under high client churn.
```rust
use axum::{extract::Request, http::StatusCode, response::IntoResponse};
use tokio::fs::File;
use tokio::io::AsyncWriteExt;
use futures_util::StreamExt;

pub async fn upload_handler(request: Request) -> Result<impl IntoResponse, StatusCode> {
    let mut body_stream = request.into_body().into_data_stream();
    let path = format!("/tmp/uploads/{}.bin", uuid::Uuid::new_v4());
    // CRITICAL BUG: If client disconnects while streaming chunks,
    // the future is dropped at .await. The open file handle stays alive
    // until OS flush and the partially written file remains orphaned on disk permanently.
    let mut file = File::create(&path).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    while let Some(chunk) = body_stream.next().await {
        let data = chunk.map_err(|_| StatusCode::BAD_REQUEST)?;
        file.write_all(&data).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    }

    // If aborted, this point is never reached, leaving disk bloat
    file.flush().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    Ok(StatusCode::CREATED)
}
```

#### Production Standard (Correct)
> **Standard**: By encapsulating the file descriptor and path within an RAII `CleanableFile` struct, any cancellation during `.await` yields will execute `Drop::drop`, removing the partial file synchronously from disk and releasing OS resources cleanly.
```rust
use axum::{extract::Request, http::StatusCode, response::IntoResponse};
use futures_util::StreamExt;
use std::path::{Path, PathBuf};
use tokio::fs::File;
use tokio::io::AsyncWriteExt;

struct CleanableFile {
    path: PathBuf,
    file: File,
    committed: bool,
}

impl CleanableFile {
    async fn create(path: PathBuf) -> std::io::Result<Self> {
        let file = File::create(&path).await?;
        Ok(Self { path, file, committed: false })
    }

    async fn commit(mut self) -> std::io::Result<PathBuf> {
        self.file.flush().await?;
        self.file.sync_all().await?;
        self.committed = true;
        Ok(self.path.clone())
    }
}

impl Drop for CleanableFile {
    fn drop(&mut self) {
        if !self.committed && self.path.exists() {
            // Deterministically purge partial artifact on future drop
            let _ = std::fs::remove_file(&self.path);
        }
    }
}

pub async fn upload_handler(request: Request) -> Result<impl IntoResponse, StatusCode> {
    let mut body_stream = request.into_body().into_data_stream();
    let staging_path = PathBuf::from(format!("/tmp/uploads/{}.tmp", uuid::Uuid::new_v4()));
    let mut staged = CleanableFile::create(staging_path).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

    while let Some(chunk) = body_stream.next().await {
        let data = chunk.map_err(|_| StatusCode::BAD_REQUEST)?;
        staged.file.write_all(&data).await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    }

    // Explicit commit prevents the drop guard from deleting the artifact
    let final_path = staged.commit().await.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
    Ok((StatusCode::CREATED, final_path.display().to_string()))
}
```

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: Axum 0.8 Cancellation-Safe Streaming Pipeline Standard

Axum 0.8 Cancellation-Safe Streaming Pipeline Standard defines an industrial-grade behavioral standard for backend engineering. Axum request futures are dropped immediately at the nearest yield point when a client terminates the connection. Streaming upload pipelines must bind all intermediate resources to deterministic RAII rollback guards to eliminate orphaned temporary files and leaked file descriptors upon mid-stream aborts. 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: Orphaned Partial Files and Leaked File Descriptors via Naked Async File Writes During Premature Client Disconnection 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 DriftOrphaned Partial Files and Leaked File Descriptors via Naked Async File Writes During Premature Client DisconnectionCritical
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 encapsulate streaming file sinks in RAII transaction guards (e.g., custom cleanup wrappers or `tempfile

Engineers MUST ALWAYS encapsulate streaming file sinks in RAII transaction guards (e.g., custom cleanup wrappers or `tempfile::NamedTempFile`) that automatically remove incomplete artifacts on drop unless explicitly committed.

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 NOT rely on sequential post-loop cleanup code in streaming handlers, as client drops cause immediate future termination at `.await` boundaries, skipping all downstream logic.

Engineers MUST NOT rely on sequential post-loop cleanup code in streaming handlers, as client drops cause immediate future termination at `.await` boundaries, skipping all downstream logic.

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

Code MUST handle `axum

Code MUST handle `axum::body::Body` consumption through bounded stream chunk adapters and forward-propagate cancellation without spawning detached background write tasks.

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

Services MUST flush and sync file descriptors synchronously or via explicit blocking offload prior to renaming/promoting temporary storage to persistent object stores.

Services MUST flush and sync file descriptors synchronously or via explicit blocking offload prior to renaming/promoting temporary storage to persistent object stores.

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

Components NEVER use naked `tokio

Components NEVER use naked `tokio::fs::File::create` with hardcoded paths directly inside streaming request loops without guaranteed unlink-on-drop mechanics.

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 Axum 0.8 Cancellation-Safe Streaming Pipeline Standard critical for AI coding assistants?

Axum request futures are dropped immediately at the nearest yield point when a client terminates the connection. Streaming upload pipelines must bind all intermediate resources to deterministic RAII rollback guards to eliminate orphaned temporary files and leaked file descriptors upon mid-stream aborts. 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 (Orphaned Partial Files and Leaked File Descriptors via Naked Async File Writes During Premature Client Disconnection) 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

Axum