This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
backendcritical PriorityID: golang-gin-clean-arch

Go Gin Clean Architecture & Explicit Error Handling

Production Go standards: strict error checking (never ignore `if err != nil`), context propagation for cancellation/timeouts, and dependency injection.

Prohibited Anti-Pattern: AI uses blank identifier `_` to suppress errors, panics in HTTP handlers, or ignores request context.

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Go Gin Clean Architecture & Explicit Error Handling - Production Go standards: strict error checking (never ignore `if err != nil`), context propagation for cancellation/timeouts, and dependency injection.
globs: **/*.go
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/golang-gin-clean-arch"
---

# Go Gin Clean Architecture & Explicit Error Handling

> **Severity**: CRITICAL | **Category**: backend
> **Anti-Pattern Warning**: AI uses blank identifier `_` to suppress errors, panics in HTTP handlers, or ignores request context.

## System Constraints
You are a senior Golang systems architect. In Go, explicit error handling is mandatory; never discard errors with `_ = fn()`. Never panic inside HTTP request handlers. Always propagate context.Context down the call tree to honor client disconnects and timeouts.

## Strict Guidelines
- Never ignore returned errors with blank identifier `_`. Check `if err != nil` and wrap with `fmt.Errorf("...: %w", err)`.
- Pass `c.Request.Context()` to all database queries and external RPC calls to respect request cancellation.
- Organize projects following Clean Architecture: handler -> service/usecase -> repository.
- Return structured error JSON with consistent machine-readable error codes.

## Bad vs Good Implementations
### Explicit Error Wrapping and Context Propagation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Discarding errors can lead to returning empty or nil data, masked database crashes, or silent data corruption.
```go
// Anti-pattern: Swallowed errors and context ignored
func (h *UserHandler) GetUser(c *gin.Context) {
    id := c.Param("id")
    user, _ := h.repo.FindByID(id) // ERROR DISCARDED!
    c.JSON(200, user)
}
```

#### Production Standard (Correct)
> **Standard**: Propagates request context, checks errors explicitly, and maps domain errors to proper HTTP response codes.
```go
// Production Standard: Explicit handling and context propagation
func (h *UserHandler) GetUser(c *gin.Context) {
    ctx := c.Request.Context()
    id := c.Param("id")

    user, err := h.service.FindByID(ctx, id)
    if err != nil {
        if errors.Is(err, apperrors.ErrNotFound) {
            c.JSON(http.StatusNotFound, gin.H{"error": "user_not_found", "message": "User does not exist"})
            return
        }
        c.JSON(http.StatusInternalServerError, gin.H{"error": "internal_error", "message": "Failed to retrieve user"})
        return
    }

    c.JSON(http.StatusOK, user)
}
```

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 Gin Clean Architecture & Explicit Error Handling

Enterprise Go microservices demand explicit error propagation, concurrency safety, and context propagation. In high-throughput Gin APIs, unbounded goroutine spawning without context timeouts or worker pools leads to file descriptor exhaustion and silent memory leaks.

Framework Paradigm Shift & Drift MechanicsAI models commonly treat Go goroutines like JavaScript promises, launching `go func() { ... }()` inside HTTP handlers without passing `c.Request.Context()` or handling panic recovery. When the client disconnects, the spawned goroutine continues running indefinitely in the background.
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
Unbounded Goroutine LeakageAI creates background goroutines using `go func()` with the Gin context `c` directlyCritical
Gin context is recycled after the HTTP handler returns; reading `c` concurrently triggers race conditions and memory corruption.
Never pass `*gin.Context` to background goroutines. Use `c.Copy()` or pass a bounded `context.WithTimeout(context.Background(), ...)`.
Swallowed Error ReturnsAI ignores returned errors: `val, _ := db.Query()`High
Hides database failures, causes silent data corruption, and prevents Prometheus error metric increments.
Always check `if err != nil` and wrap errors with domain context using `fmt.Errorf("failed to query: %w", err)`.
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

Never ignore returned errors with blank identifier `_`. Check `if err != nil` and wrap with `fmt.Errorf("...

Never ignore returned errors with blank identifier `_`. Check `if err != nil` and wrap with `fmt.Errorf("...: %w", err)`.

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

Pass `c.Request.Context()` to all database queries and external RPC calls to respect request cancellation.

Pass `c.Request.Context()` to all database queries and external RPC calls to respect request cancellation.

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

Organize projects following Clean Architecture

Organize projects following Clean Architecture: handler -> service/usecase -> repository.

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

Return structured error JSON with consistent machine-readable error codes.

Return structured error JSON with consistent machine-readable error codes.

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 should I not pass gin.Context to a goroutine?

Gin reuses `gin.Context` instances across HTTP requests via an internal sync.Pool to minimize memory allocations. If a goroutine retains a pointer to `gin.Context` after the response finishes, another incoming request will mutate that same context concurrently, resulting in catastrophic race conditions.

Q:How should database transactions be handled in Go clean architecture?

Pass `context.Context` through all service and repository layers, and manage the database transaction life-cycle with a `defer tx.Rollback()` pattern so unexpected panics or errors guarantee rollback.

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