golang-samber-oops
Structured error handling in Golang with samber/oops — error builders, stack traces, error codes, error context, error wrapping, error attributes, user-facing vs developer messages, panic recovery, and logger integration.
Install / Use
npx skills add samber/cc-skills-golang --skill golang-samber-oopsInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of golang-samber-oops
golang-samber-oops scores 93/100 on our quality scale, 636th of 4,653 Development & Engineering skills we index (top 14%).
Its SKILL.md is 10 KB long, well organised into 18 sections with 11 code examples: a thorough specification that gives an agent plenty to work with.
With 3,324 GitHub stars, it is one of the more widely adopted skills in the catalogue.
Maintenance, license and trust
- The repository was last updated 25 days ago, so golang-samber-oops is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
Safety scan
No issues foundOur scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands.
Automated pattern scan on 2026-10-02. It catches known dangerous patterns, not every risk — read a skill before letting an agent act on it.
golang-samber-oops compared with similar skills
All 4 of these similar skills score higher than golang-samber-oops; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| golang-samber-oops (this skill)by samber | 93 | 3.3k | 25d ago | SKILL.md |
| Agent-Reachby Panniantong | 100 | 87.6k | 16d ago | CLAUDE.md |
| ai-job-searchby MadsLorentzen | 100 | 44.7k | today | CLAUDE.md |
| claude-howtoby luongnv89 | 100 | 41.7k | 2d ago | CLAUDE.md |
| algorithmic-artby anthropics | 100 | 177.9k | 9d ago | SKILL.md |
Frequently asked questions
- How do I install golang-samber-oops?
- Run
npx skills add samber/cc-skills-golang --skill golang-samber-oops. The install tabs above show the steps for each supported agent. - Which AI agents does golang-samber-oops work with?
- It is written for Claude Code and OpenAI Codex, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is golang-samber-oops safe to use?
- Our scan of the whole file found no instruction hijacking, hidden characters, credential access, data exfiltration or destructive commands. It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is golang-samber-oops still maintained?
- The repository was last updated 25 days ago, so golang-samber-oops is actively maintained.
Skill content
View source on GitHubname: golang-samber-oops description: "Structured error handling in Golang with samber/oops — error builders, stack traces, error codes, error context, error wrapping, error attributes, user-facing vs developer messages, panic recovery, and logger integration. Apply when using or adopting samber/oops, or when the codebase already imports github.com/samber/oops." user-invocable: true license: MIT compatibility: Designed for Claude Code, Codex or similar harness, and for projects using Golang. metadata: author: samber version: "1.2.1" openclaw: emoji: "💥" homepage: https://github.com/samber/cc-skills-golang requires: bins: - go install: [] skill-library-version: "1.21.0" allowed-tools: Read Edit Write Glob Grep Bash(go:) Bash(golangci-lint:) Bash(git:) Agent WebFetch mcp__context7__resolve-library-id mcp__context7__query-docs Bash(godig:) Bash(gopls:) LSP mcp__gopls__ paths:
- "**/*.go"
Persona: You are a Go engineer who treats errors as structured data. Every error carries enough context — domain, attributes, trace — for an on-call engineer to diagnose the problem without asking the developer.
samber/oops Structured Error Handling
samber/oops is a drop-in replacement for Go's standard error handling that adds structured context, stack traces, error codes, public messages, and panic recovery. Variable data goes in .With() attributes (not the message string), so APM tools (Datadog, Loki, Sentry) can group errors properly. Unlike the stdlib approach (adding slog attributes at the log site), oops attributes travel with the error through the call stack.
Why use samber/oops
Standard Go errors lack context — you see connection failed but not which user triggered it, what query was running, or the full call stack. samber/oops provides:
- Structured context — key-value attributes on any error
- Stack traces — automatic call stack capture
- Error codes — machine-readable identifiers
- Public messages — user-safe messages separate from technical details
- Low-cardinality messages — variable data in
.With()attributes, not the message string, so APM tools group errors properly
This skill is not exhaustive — refer to library documentation and code examples for more information:
- For Go package docs, symbols, versions, importers, and known vulnerabilities, → See
samber/cc-skills-golang@golang-pkg-go-devskill (godig), preferred over Context7 for Go package facts. - To navigate this library's usage in your own code (definitions, call sites, diagnostics), → See
samber/cc-skills-golang@golang-goplsskill (gopls). - Context7 remains a fallback for docs not indexed on pkg.go.dev.
Core pattern: Error builder chain
All oops errors use a fluent builder pattern:
err := oops.
In("user-service"). // domain/feature
Tags("database", "postgres"). // categorization
Code("network_failure"). // machine-readable identifier
User("user-123", "email", "foo@bar.com"). // user context
With("query", query). // custom attributes
Errorf("failed to fetch user: %s", "timeout")
Terminal methods:
.Errorf(format, args...)— create a new error.Wrap(err)— wrap an existing error.Wrapf(err, format, args...)— wrap with a message.Join(err1, err2, ...)— combine multiple errors.Recover(fn)/.Recoverf(fn, format, args...)— convert panic to error
Error builder methods
| Methods | Use case |
| --- | --- |
| .With("key", value) | Add custom key-value attribute (lazy func() any values supported) |
| .WithContext(ctx, "key1", "key2") | Extract values from Go context into attributes (lazy values supported) |
| .In("domain") | Set the feature/service/domain |
| .Tags("auth", "sql") | Add categorization tags (query with err.HasTag("tag")) |
| .Code("iam_authz_missing_permission") | Set machine-readable error identifier/slug |
| .Public("Could not fetch user.") | Set user-safe message (separate from technical details) |
| .Hint("Runbook: https://doc.acme.org/doc/abcd.md") | Add debugging hint for developers |
| .Owner("team/slack") | Identify responsible team/owner |
| .User(id, "k", "v") | Add user identifier and attributes |
| .Tenant(id, "k", "v") | Add tenant/organization context and attributes |
| .Trace(id) | Add trace / correlation ID (default: ULID) |
| .Span(id) | Add span ID representing a unit of work/operation (default: ULID) |
| .Time(t) | Override error timestamp (default: time.Now()) |
| .Since(t) | Set duration based on time since t (exposed via err.Duration()) |
| .Duration(d) | Set explicit error duration |
| .Request(req, includeBody) | Attach *http.Request (optionally including body) |
| .Response(res, includeBody) | Attach *http.Response (optionally including body) |
| oops.FromContext(ctx) | Start from an OopsErrorBuilder stored in a Go context |
Common scenarios
Database/repository layer
func (r *UserRepository) FetchUser(id string) (*User, error) {
query := "SELECT * FROM users WHERE id = $1"
row, err := r.db.Query(query, id)
if err != nil {
return nil, oops.
In("user-repository").
Tags("database", "postgres").
With("query", query).
With("user_id", id).
Wrapf(err, "failed to fetch user from database")
}
// ...
}
HTTP handler layer
func (h *Handler) CreateUser(w http.ResponseWriter, r *http.Request) {
userID := getUserID(r)
err := h.service.CreateUser(r.Context(), userID)
if err != nil {
err = oops.
In("http-handler").
Tags("endpoint", "/users").
Request(r, false).
User(userID).
Wrapf(err, "create user failed")
http.Error(w, oops.GetPublic(err, "Internal server error"), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
}
Service layer with reusable builder
func (s *UserService) CreateOrder(ctx context.Context, req CreateOrderRequest) error {
builder := oops.
In("order-service").
Tags("orders", "checkout").
Tenant(req.TenantID, "plan", req.Plan).
User(req.UserID, "email", req.UserEmail)
product, err := s.catalog.GetProduct(ctx, req.ProductID)
if err != nil {
return builder.
With("product_id", req.ProductID).
Wrapf(err, "product lookup failed")
}
if product.Stock < req.Quantity {
return builder.
Code("insufficient_stock").
Public("Not enough items in stock.").
With("requested", req.Quantity).
With("available", product.Stock).
Errorf("insufficient stock for product %s", req.ProductID)
}
return nil
}
Error wrapping best practices
DO: Wrap directly, no nil check needed
// ✓ Good — Wrap returns nil if err is nil
return oops.Wrapf(err, "operation failed")
// ✗ Bad — unnecessary nil check
if err != nil {
return oops.Wrapf(err, "operation failed")
}
return nil
DO: Add context at each layer
Each architectural layer SHOULD add context via Wrap/Wrapf — at least once per package boundary (not necessarily at every function call).
// ✓ Good — each layer adds relevant context
func Controller() error {
return oops.In("controller").Trace(traceID).Wrapf(Service(), "user request failed")
}
func Service() error {
return oops.In("service").With("op", "create_user").Wrapf(Repository(), "db operation failed")
}
func Repository() error {
return oops.In("repository").Tags("database", "postgres").Errorf("connection timeout")
}
DO: Keep error messages low-cardinality
Error messages MUST be low-cardinality for APM aggregation. Interpolating variable data into the message breaks grouping in Datadog, Loki, Sentry.
// ✗ Bad — high-cardinality, breaks APM grouping
oops.Errorf("failed to process user %s in tenant %s", userID, tenantID)
// ✓ Good — static message + structured attributes
oops.With("user_id", userID).With("tenant_id", tenantID).Errorf("failed to process user")
Panic recovery
oops.Recover() MUST be used in goroutine boundaries. Convert panics to structured errors:
func ProcessData(data string) (err error) {
return oops.
In("data-processor").
Code("panic_recovered").
Hint("Check input data format and dependencies").
With("input_data", data).
Recover(func() {
riskyOperation(data)
})
}
Accessing error information
samber/oops errors implement the standard error interface. Access additional info:
if oopsErr, ok := err.(oops.OopsError); ok {
fmt.Println("Code:", oopsErr.Code())
fmt.Println("Domain:", oopsErr.Domain())
fmt.Println("Tags:", oopsErr.Tags())
fmt.Println("Context:", oopsErr.Context())
fmt.Println("Stacktrace:", oopsErr.Stacktrace())
}
// Get public-facing message with fallback
publicMsg := oops.GetPublic(err, "Something went wrong")
Output formats
fmt.Printf("%+v\n", err) // verbose with stack trace
bytes, _ := json.Marshal(err) // JSON for logging
slog.Error(err.Error(), slog.Any("error", err)) // slog integration
Context propagation
Carry error context through Go contexts:
func middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
builder := oops.
In("http").
Request(r, false).
Trace(r.Header.Get("X-Trace-ID"))
ctx := oops.WithBuilder(r.Context(), builder)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
func handler(ctx context.Context) error {
return oops.FromContext(ctx).Tags("handler", "users").Errorf("something failed")
}
For assertions, configuration, and additional logger examples, see Advanced patterns.
References
Cross-References
- → See
samber/cc-skills-golang@golang-error-handlingskill for general error handling patterns - → See
samber/cc-skills-golang@golang-observabilityskill for logger integration and structured logging
Related Skills
Agent-Reach
87.6kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
ai-job-search
44.7kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
claude-howto
41.7kA visual, example-driven guide to Claude Code — from basic concepts to advanced agents, with copy-paste templates that bring immediate value.
algorithmic-art
177.9kCreating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
