<< All versions
Skill v1.0.0
currentLLM-judged scan90/100alex123098/my-dotfiles/go-errors
──Details
PublishedOctober 23, 2026 at 07:27 AM
Content Hashsha256:f1558107c385521d...
Git SHA79838ab4898e
──Files
Files (1 file, 3.7 KB)
SKILL.md3.7 KBactive
SKILL.md · 28 lines · 3.7 KB
name: "go-errors" description: "Go error handling and context.Context propagation. Use when creating, wrapping, inspecting, or logging errors, and when propagating context across API boundaries, timeouts, or cancellation." version: 1 created: "2026-06-20" updated: "2026-06-20"
Procedure
- Error Creation: Use
errors.Newfor static messages,fmt.Errorffor dynamic. Error strings MUST be lowercase, no trailing punctuation, no prescribed action. Use sentinel errors (var ErrNotFound = errors.New("pkg: not found")) for expected conditions. Use custom error types for carrying structured data. Preallocate sentinels at package level — never inlineerrors.Newin functions called repeatedly. - Error Wrapping: Wrap errors with context using
fmt.Errorf("context: %w", err)— use%winternally to preserve chain,%vat system boundaries to hide internals. Useerrors.Join(Go 1.20+) to combine independent errors. NEVER usefmt.Errorf("%v", err)or string concatenation — those break the error chain. - Error Inspection: Use
errors.Is(err, sentinel)for sentinel matching. Useerrors.As(err, &target)for typed chain inspection (Go <1.26). Useerrors.AsType[T](err)(Go 1.26+) for type-safe chain inspection. NEVER use direct comparison (err == ErrNotFound) or bare type assertions for errors that may be wrapped. - Single Handling Rule: Errors are EITHER logged OR returned — NEVER both. Log-and-return creates duplicate log lines and makes aggregators unreliable. Log at the top-level handler; return with wrapping context from lower layers. Always check returned errors — never discard with
_. - Context Propagation:
context.Contextis Go's mechanism for cancellation, deadlines, and request-scoped values. ctx MUST be the first parameter namedctx. NEVER store context in a struct — pass explicitly. NEVER pass nil — usecontext.TODO()if unsure. Propagate the same ctx through the entire call chain.cancel()must be called on all control-flow paths forWithCancel/WithTimeout/WithDeadline.context.Background()only at top-level (main, init, tests). Usecontext.WithoutCancel(Go 1.21+) for background work that outlives the parent. - Structured Error Logging: Use
log/slog(Go 1.21+) — notfmt.Printlnorlog.Printf. Useslog.ErrorContext(ctx, "msg", "err", err)to correlate with traces. Log with context variants (slog.InfoContext). Use log levels appropriately: Debug for dev, Info for normal, Warn for degraded, Error for failures needing attention. Never expose technical errors to users — translate to user-friendly messages, log technical details server-side.
Pitfalls
- Returning a typed nil pointer in an interface creates a non-nil interface (
var h *MyHandler; return hyieldsinterface{type: *MyHandler, value: nil}which is != nil). Return untypednilfor the nil case. - Using
%vinstead of%wwhen wrapping breakserrors.Is/errors.Aschain inspection. - Calling
cancel()at every return path is essential — if multiple goroutines share the ctx, one cancel leaks the rest. - Creating new
context.Background()in the middle of a request path breaks the cancellation chain. - Using
context.Valuefor function parameters — context values are for request-scoped metadata only (request ID, user ID). Keys must be unexported types to prevent collisions.
Verification
go vet ./...catches unused results, canceled context not used.- No
fmt.Printlnorlog.Printfin production code paths — all logging usesslog. - No
if err != nil { return err }without adding context viafmt.Errorf. - Every
context.WithCancel/WithTimeout/WithDeadlinehas a matchingcancel()call on all paths.