Fundamentals 25 min read

Deep Dive into Go's pkg/errors Package: Design, Implementation, and Usage

This article explains Go's error‑handling shortcomings, introduces the popular third‑party pkg/errors library, demonstrates how to wrap errors with additional context and stack traces, and provides a detailed line‑by‑line walkthrough of its source files (errors.go, go113.go, stack.go) to reveal the underlying design and implementation.

Go Programming World
Go Programming World
Go Programming World
Deep Dive into Go's pkg/errors Package: Design, Implementation, and Usage

Go's built‑in error handling follows the simple "errors are values" philosophy, but it lacks built‑in support for attaching extra context such as user identifiers or stack traces, which are common requirements in real‑world development.

The pkg/errors library (over 8.2k stars on GitHub) fills this gap by providing functions that create errors with stack information ( New , Errorf ), wrap existing errors with additional messages ( WithMessage , Wrap ), and expose utilities compatible with Go 1.13 error chains ( Is , As , Unwrap ).

Typical usage looks like this:

newErr := fmt.Errorf("user %d is err: %w", userID, err)

Here the %w verb preserves the original error, allowing errors.Unwrap(newErr) to retrieve the root cause.

The library also offers a richer API:

func New(message string) error {
    return &fundamental{msg: message, stack: callers()}
}

func WithMessage(err error, message string) error {
    if err == nil { return nil }
    return &withMessage{cause: err, msg: message}
}

func Wrap(err error, message string) error {
    if err == nil { return nil }
    err = &withMessage{cause: err, msg: message}
    return &withStack{err, callers()}
}

func callers() *stack {
    const depth = 32
    var pcs [depth]uintptr
    n := runtime.Callers(3, pcs[:])
    st := pcs[0:n]
    return &st
}

The source is organized into three files:

errors.go defines three error structs— fundamental (basic error with stack), withStack (adds a stack to any error), and withMessage (adds a message to any error)—and implements the Error and Format methods that control how %v , %+v , %s , and %q verbs render the error.

go113.go provides thin wrappers around the standard library's errors.Is , errors.As , and errors.Unwrap functions, ensuring compatibility with Go 1.13's error‑wrapping semantics.

stack.go implements stack capture and formatting. The callers function uses runtime.Callers (with a skip of 3 frames) to obtain program counters, which are stored in a stack type ( []uintptr ). The stack.Format method iterates over these PCs, converts each to a Frame , and prints file, line, and function information when the %+v verb is used.

Key types in stack.go include:

type stack []uintptr

type Frame uintptr

func (f Frame) pc() uintptr { return uintptr(f) - 1 }
func (f Frame) file() string { fn := runtime.FuncForPC(f.pc()); if fn == nil { return "unknown" }; file, _ := fn.FileLine(f.pc()); return file }
func (f Frame) line() int { fn := runtime.FuncForPC(f.pc()); if fn == nil { return 0 }; _, line := fn.FileLine(f.pc()); return line }
func (f Frame) name() string { fn := runtime.FuncForPC(f.pc()); if fn == nil { return "unknown" }; return fn.Name() }

When an error is printed with %+v , the formatter walks the stack, producing output such as:

b error: a error
main.a
    /path/to/main.go:11
main.b
    /path/to/main.go:15
main.main
    /path/to/main.go:30
runtime.main
    ...
runtime.goexit
    ...

In summary, pkg/errors offers a simple yet powerful way to enrich Go errors with contextual messages and stack traces, while remaining compatible with the language's evolving error‑wrapping features. It is still widely used despite the official Go 2 error proposal, making it a valuable tool for backend developers seeking robust error handling.

stack traceprogrammingGoError handlingerrorsgo13pkg/errors
Go Programming World
Written by

Go Programming World

Mobile version of tech blog https://jianghushinian.cn/, covering Golang, Docker, Kubernetes and beyond.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.