Skip to content

whynot00/e

Repository files navigation

Package e - Error Wrapper for Go

Go Reference Go Report Card License: MIT

e is a lightweight Go package providing enhanced error wrapping with stack trace capture and structured logging support using Go's log/slog package.

Features

  • Wrap errors with automatic stack trace capture
  • Attach custom contextual messages to errors
  • Add structured key–value fields to errors for additional context
  • Compatible with Go standard library errors.Is and errors.As
  • Produce structured logs with detailed error trace using slog.Group
  • Simplifies function names in stack traces for better readability
  • Recover from panics and convert them into structured errors (with optional stack trace and fatal handling)

Installation

go get github.com/whynot00/e

Usage

Wrapping errors

Wrap an existing error to capture the current stack frame:

err := errors.New("database error")

wrappedErr := e.Wrap(err)

Wrap with a custom message describing context:

wrappedErr := e.WrapWithMessage(err, "failed to load user profile")

Structured logging with slog

Integrate with log/slog for rich structured logs:

logger := slog.New(slog.NewJSONHandler(os.Stdout))

err := e.WrapWithMessage(someError, "additional context")

logger.Error("operation failed", e.SlogGroup(err))

Example output:

{
  "level": "error",
  "msg": "operation failed",
  "error": {
    "error_text": "some error message",
    "stack_trace": [
      {
        "file": "/path/to/file.go",
        "function": "functionName",
        "line": 42,
        "message": "additional context"
      },
      {
        "file": "/path/to/other.go",
        "function": "otherFunction",
        "line": 10
      }
    ]
  }
}

This logs the error message along with a detailed stack trace and custom messages.

JSON serialization

Wrapped errors implement json.Marshaler, producing structured JSON including error message and stack trace:

jsonData, err := json.Marshal(wrappedErr)
if err != nil {
    // handle error
}
fmt.Println(string(jsonData))

Example output:

{
  "error": "sql: no rows in result set",
  "stack_trace": [
    {
      "file": "/path/to/main.go",
      "function": "main",
      "line": 15
    },
    {
      "file": "/path/to/main.go",
      "function": "work",
      "line": 22
    },
    {
      "file": "/path/to/main.go",
      "function": "anotherWork",
      "line": 32,
      "message": "fetching user data failed"
    }
  ]
}

Custom Fields Support

You can now attach structured key-value fields to wrapped errors for richer context in logs or serialized output. Creating an error with fields:

err := someOperation()
if err != nil {
    err = e.WrapWithFields(err,
        e.Field("user_id", 42),
        e.Field("operation", "database insert"),
    )
}

Example output (structured via slog.Group or JSON):

{
  "error": {
    "error_text": "insert failed",
    "stack_trace": [...],
    "user_id": 42,
    "operation": "database insert"
  }
}

Panic recovery

The package provides helpers for safe panic recovery with optional stack trace capture and structured handling.

defer e.Recover(nil, func(err error) {
    log.Println("panic recovered:", err)
})

Or send to a channel in a goroutine:

errCh := make(chan error, 1)
go func() {
    defer e.RecoverToChannel(nil, errCh)
    // potentially panicking code
}()

Example output (structured via slog.Group or JSON):

{
  "error": "panic: runtime error: index out of range",
  "stack_trace": [
    {
      "file": "/app/service.go",
      "function": "handleRequest",
      "line": 87
    },
    {
      "file": "/app/controller.go",
      "function": "Serve",
      "line": 45
    }
  ]
}

Supports Fatal termination,RecoverOnly suppression, and optional WithoutStack mode.

API

func Wrap(err error) error

Wraps an error with a captured stack frame; returns nil if input is nil.

func WrapWithMessage(err error, msg string) error

Wraps an error with a stack frame and attaches a custom message.

func WrapWithFields(err error, fields ...Fields) error

Wraps an error with a stack frame and attaches structured key–value fields for logging or serialization.

func SlogGroup(err error) slog.Attr

Returns a slog.Attr containing the error message and stack trace as a slog.Group, suitable for structured logging.

func WrapRecovered(opts *RecoverOpts, r any) error

Wraps a value returned from recover() into an error, by default capturing a filtered stack trace.

func Recover(opts *RecoverOpts, callback func(error))

Intercepts and recovers from a panic. Wraps the recovered value as an error and invokes the provided callback.

func RecoverToChannel(opts *RecoverOpts, errChan chan<- error)

Alternative to Recover for use in goroutines. Recovers from a panic and sends the error into the provided channel. Returns a slog.Attr containing the error message and stack trace as a slog.Group, suitable for structured logging.

About

Minimal error wrapping with stack trace and structured slog logging. No dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages