This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: go-iter-seq-resource-leak-fence

Go 1.24 iter.Seq and iter.Pull Concurrency Resource Leak Mitigation Fence

Enforces mandatory, unconditional invocation of the stop closure returned by iter.Pull/iter.Pull2 via defer and guarantees unblocked defer execution within custom iter.Seq/iter.Seq2 push producers upon yield rejection. Prevents paired goroutine leaks, orphaned database cursors, and deadlocked gRPC streams across early break, return, or panic paths in high-throughput pipelines.

Prohibited Anti-Pattern: Orphaning iter.Pull Goroutines and Leaking Network Handles via Omitted stop() Calls on Early Exit

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Go 1.24 iter.Seq and iter.Pull Concurrency Resource Leak Mitigation Fence - Enforces mandatory, unconditional invocation of the stop closure returned by iter.Pull/iter.Pull2 via defer and guarantees unblocked defer execution within custom iter.Seq/iter.Seq2 push producers upon yield rejection. Prevents paired goroutine leaks, orphaned database cursors, and deadlocked gRPC streams across early break, return, or panic paths in high-throughput pipelines.
globs: **/*.go
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/go-iter-seq-resource-leak-fence"
---

# Go 1.24 iter.Seq and iter.Pull Concurrency Resource Leak Mitigation Fence

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: Orphaning iter.Pull Goroutines and Leaking Network Handles via Omitted stop() Calls on Early Exit

## System Constraints
You are a Principal Go Architect enforcing memory safety and goroutine lifecycle invariants under Go 1.24 iter.Seq and iter.Pull specifications. You must reject any code where iter.Pull or iter.Pull2 is invoked without an immediate, unconditional 'defer stop()' registration, or where custom iter.Seq push iterators ignore false return values from yield callbacks or block deferred cleanups on unbuffered synchronization primitives.

## Strict Guidelines
- Engineers MUST ALWAYS invoke 'defer stop()' immediately following any call to iter.Pull or iter.Pull2, before any branching, error checking, or pulling occurs.
- Engineers MUST NEVER manually call 'stop()' exclusively inside exit branches; cleanup must be bound to function exit via defer to guarantee execution during panics or unexpected returns.
- Code generating custom iter.Seq or iter.Seq2 producers MUST immediately return when yield(...) returns false, ensuring deferred resource cleanups (e.g., db.Rows.Close(), stream.CloseSend()) execute without delay.
- Custom iterator producers MUST NOT perform blocking channel sends or unbounded mutex acquisitions after yield returns false.
- Services consuming pull iterators over external network or context-bound sources MUST couple the iterator's lifecycle to a parent context.Context to prevent deadlocks if the consumer loop hangs.
- Components NEVER re-invoke next() after next() has returned ok == false or after stop() has been called.

## Bad vs Good Implementations
### Mitigating Goroutine and Channel Leaks with iter.Pull in Streaming Pipelines

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: iter.Pull spawns an internal paired goroutine running the iterator function until completion or until stop() is executed. By failing to register 'defer stop()' immediately after initialization, early returns on error or context cancellation skip stop(), causing the background goroutine, its call stack, and any resources acquired inside the sequence to leak permanently.
```go
package pipeline

import (
	"context"
	"fmt"
	"iter"
)

// Bad: Omitting defer stop() leaks the background goroutine spawned by iter.Pull
// whenever an early return or break condition occurs.
func ProcessStreamBad(ctx context.Context, seq iter.Seq[string]) error {
	next, stop := iter.Pull(seq)
	// BUG: If processItem fails or context cancels, stop() is never called,
	// stranding the background iterator goroutine indefinitely.
	for {
		val, ok := next()
		if !ok {
			stop()
			break
		}
		if err := ctx.Err(); err != nil {
			return err // LEAK: stop() bypassed
		}
		if val == "invalid" {
			return fmt.Errorf("invalid item encountered") // LEAK: stop() bypassed
		}
	}
	return nil
}
```

#### Production Standard (Correct)
> **Standard**: Placing 'defer stop()' immediately after 'iter.Pull' ensures that regardless of whether the loop breaks naturally, encounters an error, detects context cancellation, or panics, the paired pull-goroutine is properly signaled to unblock and terminate, allowing all deferred resource releases inside the underlying iter.Seq to execute safely.
```go
package pipeline

import (
	"context"
	"fmt"
	"iter"
)

// Good: Immediate defer stop() ensures deterministic goroutine termination
// across all exit paths, panics, and early returns.
func ProcessStreamGood(ctx context.Context, seq iter.Seq[string]) error {
	next, stop := iter.Pull(seq)
	defer stop() // INVARIANT: Guaranteed cleanup across all control flow branches

	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		default:
		}

		val, ok := next()
		if !ok {
			return nil
		}

		if val == "invalid" {
			return fmt.Errorf("invalid item encountered: %s", val)
		}
	}
}
```

### Prompt Resource Cleanup in Custom Push Iterators (iter.Seq2)

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: In Go push iterators, yield returning false indicates that the consumer requested termination (e.g., via break or return). Failing to inspect the boolean returned by yield() prevents the producer from terminating early, prolonging connection holding times and delaying deferred cleanup.
```go
package storage

import (
	"database/sql"
	"iter"
)

// Bad: Ignoring yield return value holds DB locks and cursor open.
func StreamRecordsBad(db *sql.DB, query string) iter.Seq2[int, string] {
	return func(yield func(int, string) bool) {
		rows, err := db.Query(query)
		if err != nil {
			return
		}
		defer rows.Close()

		for rows.Next() {
			var id int
			var payload string
			_ = rows.Scan(&id, &payload)
			// BUG: If yield returns false (caller broke out), continuing or ignoring
			// causes wasted queries and delays defer rows.Close() execution.
			yield(id, payload)
		}
	}
}
```

#### Production Standard (Correct)
> **Standard**: Checking 'if !yield(...) { return }' guarantees that when downstream consumers terminate early, the producer exits its loop immediately, invoking 'defer rows.Close()' without delay and returning database connections back to the connection pool instantaneously.
```go
package storage

import (
	"database/sql"
	"iter"
)

// Good: Immediate return when yield returns false guarantees instant cleanup.
func StreamRecordsGood(db *sql.DB, query string) iter.Seq2[int, string] {
	return func(yield func(int, string) bool) {
		rows, err := db.Query(query)
		if err != nil {
			return
		}
		defer rows.Close() // Invariant: Guaranteed to run as soon as caller terminates

		for rows.Next() {
			var id int
			var payload string
			if err := rows.Scan(&id, &payload); err != nil {
				return
			}
			// INVARIANT: Check yield result and break immediately if consumer stops.
			if !yield(id, payload) {
				return
			}
		}
	}
}
```

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: Go 1.24 iter.Seq and iter.Pull Concurrency Resource Leak Mitigation Fence

Go 1.24 iter.Seq and iter.Pull Concurrency Resource Leak Mitigation Fence defines an industrial-grade behavioral standard for backend engineering. Enforces mandatory, unconditional invocation of the stop closure returned by iter.Pull/iter.Pull2 via defer and guarantees unblocked defer execution within custom iter.Seq/iter.Seq2 push producers upon yield rejection. Prevents paired goroutine leaks, orphaned database cursors, and deadlocked gRPC streams across early break, return, or panic paths in high-throughput pipelines. 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: Orphaning iter.Pull Goroutines and Leaking Network Handles via Omitted stop() Calls on Early Exit 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 DriftOrphaning iter.Pull Goroutines and Leaking Network Handles via Omitted stop() Calls on Early ExitCritical
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 invoke 'defer stop()' immediately following any call to iter.Pull or iter.Pull2, before any branching, error checking, or pulling occurs.

Engineers MUST ALWAYS invoke 'defer stop()' immediately following any call to iter.Pull or iter.Pull2, before any branching, error checking, or pulling occurs.

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 NEVER manually call 'stop()' exclusively inside exit branches

Engineers MUST NEVER manually call 'stop()' exclusively inside exit branches; cleanup must be bound to function exit via defer to guarantee execution during panics or unexpected returns.

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 generating custom iter.Seq or iter.Seq2 producers MUST immediately return when yield(...) returns false, ensuring deferred resource cleanups (e.g., db.Rows.Close(), stream.CloseSend()) execute without delay.

Code generating custom iter.Seq or iter.Seq2 producers MUST immediately return when yield(...) returns false, ensuring deferred resource cleanups (e.g., db.Rows.Close(), stream.CloseSend()) execute without delay.

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

Custom iterator producers MUST NOT perform blocking channel sends or unbounded mutex acquisitions after yield returns false.

Custom iterator producers MUST NOT perform blocking channel sends or unbounded mutex acquisitions after yield returns false.

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 consuming pull iterators over external network or context-bound sources MUST couple the iterator's lifecycle to a parent context.Context to prevent deadlocks if the consumer loop hangs.

Services consuming pull iterators over external network or context-bound sources MUST couple the iterator's lifecycle to a parent context.Context to prevent deadlocks if the consumer loop hangs.

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 re-invoke next() after next() has returned ok == false or after stop() has been called.

Components NEVER re-invoke next() after next() has returned ok == false or after stop() has been called.

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 Go 1.24 iter.Seq and iter.Pull Concurrency Resource Leak Mitigation Fence critical for AI coding assistants?

Enforces mandatory, unconditional invocation of the stop closure returned by iter.Pull/iter.Pull2 via defer and guarantees unblocked defer execution within custom iter.Seq/iter.Seq2 push producers upon yield rejection. Prevents paired goroutine leaks, orphaned database cursors, and deadlocked gRPC streams across early break, return, or panic paths in high-throughput pipelines. 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 (Orphaning iter.Pull Goroutines and Leaking Network Handles via Omitted stop() Calls on Early Exit) 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

Go