affaan-m/ECC · warning
get user %s: %w
Error message
get user %s: %w
What it means
A Go fmt.Errorf format string demonstrated in the go-review command as the recommended fix for 'Missing Error Context'. The reviewer flags a bare `return err` and recommends wrapping with fmt.Errorf using the %w verb to preserve the underlying error while adding context (here, the user id). %w (not %v) preserves errors.Is/errors.As unwrapping.
Source
Thrown at commands/go-review.md:119
cacheMu sync.RWMutex
)
func GetSession(id string) *Session {
cacheMu.RLock()
defer cacheMu.RUnlock()
return cache[id]
}
```
[HIGH] Missing Error Context
File: internal/handler/user.go:28
Issue: Error returned without context
```go
return err // No context
```
Fix: Wrap with context
```go
return fmt.Errorf("get user %s: %w", userID, err)
```
## Summary
- CRITICAL: 1
- HIGH: 1
- MEDIUM: 0
Recommendation: FAIL: Block merge until CRITICAL issue is fixed
```
## Approval Criteria
| Status | Condition |
|--------|-----------|
| PASS: Approve | No CRITICAL or HIGH issues |
| WARNING: Warning | Only MEDIUM issues (merge with caution) |
| FAIL: Block | CRITICAL or HIGH issues found |
View on GitHub (pinned to 01e15490f0)
Solutions
- Wrap at every layer boundary with fmt.Errorf("<verb> <entity> %s: %w", id, err) — one wrap per layer.
- Use %w (not %v) so the error chain stays unwrappable for errors.Is/errors.As.
- Include just enough context (entity type + identifier) without duplicating the message at every layer.
- Add a linter (wrapcheck, errcheck) to fail CI on bare `return err`.
Example fix
// before
return err // No context
// after
return fmt.Errorf("get user %s: %w", userID, err) Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
if err := svc.GetUser(ctx, id); err != nil {
if errors.Is(err, domain.ErrNotFound) {
http.NotFound(w, r)
return
}
log.Printf("get user %s failed: %v", id, err)
http.Error(w, "internal error", http.StatusInternalServerError)
} Prevention
- Wrap every returned error with fmt.Errorf("...: %w", err) — one wrap per layer.
- Use %w, never %v, when you need errors.Is to keep working.
- Add wrapcheck to CI to catch bare `return err`.
When it happens
Trigger: A handler returns `err` directly from a service call. The reviewer pattern recommends `return fmt.Errorf("get user %s: %w", userID, err)` so the eventual log/response includes which user the lookup was for. The error fires wherever the original err was non-nil.
Common situations: Bare `return err` throughout a layered codebase leaving logs with no idea which entity/route failed; using %v instead of %w which breaks errors.Is at the handler; format string with %w but no wrapped error (compile-time invisible).
Related errors
AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13).
Data as JSON: /api/errors/dedfb29d7f39993d.
Report an issue: GitHub.