SkillAgentSearch skills...

Oops

🔥 Error handling library with context, assertion, stack trace and source fragments

Install / Use

/learn @samber/Oops

README

Oops - Structured Error Handling for Go

Transform your Go error handling from "oops!" to "aha!" moments

tag Go Version GoDoc Build Status Go report Coverage Contributors License

Oops is a comprehensive Go error handling library that provides structured error management with rich contextual information. It's designed as a drop-in replacement for Go's built-in error, adding powerful features like stack traces, source code fragments, structured attributes, and developer-friendly debugging hints.

🎯 Key Features:

  • 🔧 Drop-in Replacement: Seamlessly replaces standard Go error handling
  • 📊 Rich Context: Add structured attributes, user info
  • 🐛 Debug-Friendly: Out-of-the-box stacktraces and source code fragments
  • 🔗 Error Chaining: Wrap and compose errors with additional context
  • 🛡️ Panic Recovery: Built-in panic handling with error conversion
  • ✅ Assertions: One-line assertion helpers for validation
  • ⚡ Performance: Zero dependencies, lightweight and fast
  • 📝 Logger Integration: Works with all major Go logging libraries
  • ✂️ Separation of Concerns: Error handling and logging are separate jobs
  • 🍳 Easy Integration: No large refactoring required

[!WARNING]
Important: This is NOT a logging library. oops should complements your existing logging toolchain (zap, zerolog, logrus, slog, go-sentry...).

🥷 Start hacking oops with this playground.

<div align="center"> <hr> <sup><b>Sponsored by:</b></sup> <br> <a href="https://cast.ai/samuel"> <div> <img src="https://github.com/user-attachments/assets/502f8fa8-e7e8-4754-a51f-036d0443e694" width="200" alt="Cast AI"> </div> <div> Cut Kubernetes & AI costs, boost application stability </div> </a> <br> <a href="https://www.dash0.com?utm_campaign=148395251-samber%20github%20sponsorship&utm_source=github&utm_medium=sponsorship&utm_content=samber"> <div> <img src="https://github.com/user-attachments/assets/b1f2e876-0954-4dc3-824d-935d29ba8f3f" width="200" alt="Dash0"> </div> <div> 100% OpenTelemetry-native observability platform<br>Simple to use, built on open standards, and designed for full cost control </div> </a> <hr> </div> <img align="right" title="Oops gopher logo" alt="logo: thanks Gimp" width="350" src="https://github.com/user-attachments/assets/7e02dcc5-5c07-43de-a7e0-a16d2dd0a73d">

Table of content

Context rich error handling

In a few minutes, your logs will look like this:

<div style="text-align:center;"> <img alt="Why 'oops'?" src="./assets/motivation.png" style="max-width: 650px;"> </div>

🚀 Install

go get github.com/samber/oops

# AI Agent Skill:
npx skills add https://github.com/samber/cc-skills-golang --skill golang-samber-oops

This library is v1 and follows SemVer strictly.

No breaking changes will be made to APIs before v2.0.0.

This library has no dependencies outside the Go standard library.

💡 Quick start

This library provides a simple error builder for composing structured errors, with contextual attributes and stack trace.

Since oops.OopsError implements the error interface, you will be able to compose and wrap native errors with oops.OopsError.

import "github.com/samber/oops"

func main() {
    // Simple error with context
    err := oops.
        In("user-service").
        Tags("database", "postgres").
        Code("network_failure").
        User("user-123", "email", "foo@bar.com").
        With("path", "/hello/world").
        Errorf("failed to fetch user: %s", "connection timeout")
    
    // Error wrapping
    if err != nil {
        return oops.
            Trace("req-123").
            With("product_id", "456").
            Wrapf(err, "user operation failed")
    }
}

🧠 Spec

GoDoc: https://godoc.org/github.com/samber/oops

Error builder

| Method | Description | | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | .New(message string) error | Formats returns oops.OopsError object that satisfies error | | .Errorf(format string, args ...any) error | Formats an error and returns oops.OopsError object that satisfies error | | .Wrap(err error) error | Wraps an error into an oops.OopsError object that satisfies error | | .Wrapf(err error, format string, args ...any) error | Wraps an error into an oops.OopsError object that satisfies error and formats an error message | | .Recover(cb func()) error | Handle panic and returns oops.OopsError object that satisfies error. | | .Recoverf(cb func(), format string, args ...any) error | Handle panic and returns oops.OopsError object that satisfies error and formats an error message. | | .Assert(condition bool) OopsErrorBuilder | Panics if condition is false. Assertions can be chained. | | .Assertf(condition bool, format string, args ...any) OopsErrorBuilder | Panics if condition is false and formats an error message. Assertions can be chained. | | .Join(err1 error, err2 error, ...) error | Join returns an error that wraps the given errors. |

Examples

// with error wrapping
err0 := oops.
    In("repository").
    Tags("database", "sql").
    Wrapf(sql.Exec(query), "could not fetch user")  // Wrapf returns nil when sql.Exec() is nil

// with panic recovery
err1 := oops.
    In("repository").
    Tags("database", "sql").
    Recover(func () {
        panic("caramba!")
    })

// with assertion
err2 := oops.
    In("repository").
    Tags("database", "sql").
    Recover(func () {
        // ...
        oops.Assertf(time.Now().Weekday() == 1, "This code should run on Monday only.")
        // ...
    })

// oops.New
err3 := oops.
    In("repository").
    Tags("database", "sql").
    New("an error message")

// oops.Errorf
err4 := oops.
    In("repository").
    Tags("database", "sql").
    Errorf("an error message: %d", 42)

Context

The library provides an error builder. Each method can be used standalone (eg: oops.With(...)) or from a previous builder instance (eg: oops.In("iam").User("user-42")).

The oops.OopsError builder must finish with either .Errorf(...), .Wrap(...), .Wrapf(...), .Join(...), .Recover(...) or .Recoverf(...).

| Builder method | Getter | Description | | --------------------------------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | .With(string, any) | err.Context() map[string]any | Supply a list of attributes key+value. Values of type func() any {} are accepted and evaluated lazily. | | .WithContext(context.Context, ...any) | err.Context() map[string]any | Supply a list of values declared in context. Values of type func() any {} are accepted and evaluated lazily. | | .Code(any) | err.Code() any | Set a code or slug that describes the error. Error messages are intended to be read by humans, but such code is expected to be read by machines and be transported over different services | | .Public(string) | err.Public() string | Set a message that is safe to show to an end user | | .Time(time.Time) | err.Time() time.Time

View on GitHub
GitHub Stars894
CategoryDevelopment
Updated7h ago
Forks35

Languages

Go

Security Score

100/100

Audited on Mar 27, 2026

No findings