errx/README.md
2026-04-25 18:58:23 +00:00

2.1 KiB

errx

Simple custom error wrapper utility library for my Go projects.

errx records the operation where each error happened and chains those operations together as the error bubbles up. The result is a readable breadcrumb instead of a runtime stack trace:

users.Get: user=42: db.Query: connection refused

Usage

Each function declares its op and wraps errors as it returns them:

import "git.juancwu.dev/juancwu/errx"

func (s *Store) Get(id int) (*User, error) {
    const op = "users.Get"

    row, err := s.db.Query(id)
    if err != nil {
        return nil, errx.Wrapf(op, err, "user=%d", id)
    }
    if row == nil {
        return nil, errx.New(op, "not found")
    }
    return row, nil
}

The four constructors:

errx.New(op, msg)                        // fresh error, static msg
errx.Newf(op, format, args...)           // fresh error, formatted msg
errx.Wrap(op, err)                       // wrap, no extra msg (nil-safe)
errx.Wrapf(op, err, format, args...)     // wrap with formatted msg (nil-safe)

Wrap and Wrapf return nil when passed a nil error, so you can chain them without an extra guard:

return errx.Wrap(op, s.commit())

Interop

*errx.Error implements Unwrap, so errors.Is and errors.As walk the chain as expected:

if errors.Is(err, io.EOF) { ... }

var e *errx.Error
if errors.As(err, &e) {
    log.Printf("op=%s", e.Op)
}

Development

This repo uses Task as its task runner. After cloning:

task install:tools   # installs github.com/mfridman/tparse
task                 # vet + tests

Common targets:

Task What it does
task vet + test (the default)
task test go test ./... piped through tparse
task test:race tests under the race detector
task vet go vet ./...
task fmt gofmt -w .
task tidy go mod tidy