errors

package module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 6 Imported by: 0

README

errors

Test Status Coverage Status MIT License PkgGoDev

Standard-compatible Go errors with stack traces and no external dependencies.

Synopsis

import (
    "fmt"
    "io"

    "github.com/Songmu/errors"
)

err := errors.Errorf("read config: %w", io.EOF)
fmt.Println(err)            // read config: EOF
fmt.Println(errors.Is(err, io.EOF)) // true
fmt.Printf("%+v\n", err)    // message, error tree, and stack traces

Description

New, Errorf, and non-nil Join capture the calling goroutine's stack. Messages, %w handling, child order, and single/multiple Unwrap shapes follow the standard library. Is, As, AsType, and Unwrap delegate to errors; ErrUnsupported is the standard sentinel. There are no Wrap or Cause APIs: use Errorf("operation: %w", err) for context and Join for multiple causes.

Error(), %s, %v, and %q remain message-only. %+v prints the message, then a traces: tree in outer-to-inner order. Each node has a branch path (root/0, root/1, etc.); captured frames show the function followed by an indented file:line. Standard wrappers remain visible as untraced nodes. The tree format is library-specific, not a Go standard.

The root message is complete whenever Error() succeeds. Nested library Join nodes show the number of causes instead of repeating their aggregate messages. Nested standard-library joins instead show their aggregate messages, subject to the same four-line and 256-byte limits as other nested nodes. Omitted message content is marked explicitly. This keeps deeply nested aggregates from flooding diagnostic output.

Standard fmt.Errorf and errors.Join do not propagate detailed formatting. If either is outermost, use the output-only adapter:

err := fmt.Errorf("start service: %w", errors.New("read failed"))
fmt.Printf("%+v\n", errors.Formatter(err))

Formatter neither captures a stack nor wraps the error; Formatter(nil) prints <nil>. It follows both forms of Unwrap and displays all branches, including repeated references. It does not read other libraries' stack formats or recover causes hidden with %v.

Stacks retain at most 64 program counters and are expanded only for detailed output. Common caller-frame suffixes are omitted only between a node and its nearest traced ancestor on the same branch; the capture frame always remains. Truncated stacks are marked and not used for suffix comparison. Tree traversal is limited to 64 levels (root included) and 1024 nodes, with explicit omission markers. This bounds cyclic traversal without requiring comparable errors; user-defined Error and Unwrap methods must still terminate. In detailed output, panics are marked without preventing later siblings from being displayed. Concurrent formatting does not mutate captured stacks.

A trace describes the goroutine at construction, not every return step or an external error's original location. A package-level New captures initialization: add context with Errorf("operation: %w", ErrSentinel) at the return site. Use plain %w for wrapping; %+w can embed the child's detailed output in the message, just as with fmt.Errorf.

slog's built-in default handler and slog.TextHandler format error attributes with %+v, so passing a traced error directly can include traces and local source paths. slog.JSONHandler normally uses Error() instead. Pass err.Error() for message-only attributes, or fmt.Sprintf("%+v", errors.Formatter(err)) for explicit details. There is no logger-specific integration. Stack capture adds cost; the small API and lack of dependencies are not a claim of standard-library performance.

Installation

Requires Go 1.26 or later for the standard library's errors.AsType.

The go directive in go.mod records this library's oldest supported Go version, not a pinned development toolchain. Newer Go toolchains may be used without raising that minimum.

% go get github.com/Songmu/errors

Development

Run go test -race ./... and go vet ./.... Benchmarks separate construction from ordinary and detailed formatting: go test -run '^$' -bench . -benchmem.

After changing GitHub Actions dependencies, run gh actions-lock and commit .github/workflows/actions.lock with the workflow changes. Install the tool with gh extension install github/gh-actions-lock.

Author

Songmu

Documentation

Overview

Package errors provides standard-compatible errors with stack traces.

New, Errorf, and Join capture the calling goroutine's stack. Ordinary formatting preserves the error message; %+v prints the error tree and traces. Use Formatter when a standard-library wrapper is the outermost error.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrUnsupported = stderrors.ErrUnsupported

ErrUnsupported is the standard library's unsupported-operation sentinel.

Functions

func As

func As(err error, target any) bool

As finds the first error in err's tree matching target, using errors.As.

func AsType

func AsType[E error](err error) (E, bool)

AsType finds the first error in err's tree matching E, using errors.AsType.

func Errorf

func Errorf(format string, args ...any) error

Errorf formats an error using fmt.Errorf, preserving its message and unwrap shape, and captures a stack at the call site. Use %w to wrap causes.

Example
package main

import (
	"fmt"
	"io"

	"github.com/Songmu/errors"
)

func main() {
	err := errors.Errorf("read config: %w", io.EOF)
	fmt.Println(err)
	fmt.Println(errors.Is(err, io.EOF))
}
Output:
read config: EOF
true

func Formatter

func Formatter(err error) fmt.Formatter

Formatter returns an output-only adapter for err. It does not capture a stack or change the error tree. %+v traverses both forms of Unwrap, including standard-library wrappers; other string formats use err.Error().

A nil error formats as "<nil>". Traversal stops at a depth of 64 or 1024 nodes and prints an omission marker, including for cyclic error trees. The root message is complete when Error succeeds. Nested Join messages are summarized; other nested messages are limited to four lines and 256 bytes with an omission marker. Panics are marked without suppressing later siblings. Error and Unwrap methods must themselves terminate.

Example
package main

import (
	"fmt"

	"github.com/Songmu/errors"
)

func main() {
	err := fmt.Errorf("start service: %w", errors.New("read failed"))
	// Use %+v instead of %s to include the retained stack trace.
	fmt.Printf("%s\n", errors.Formatter(err))
}
Output:
start service: read failed

func Is

func Is(err, target error) bool

Is reports whether any error in err's tree matches target, using errors.Is.

func Join

func Join(errs ...error) error

Join joins non-nil errors using errors.Join and captures a stack at the call site. It returns nil if every argument is nil.

Example
package main

import (
	"fmt"

	"github.com/Songmu/errors"
)

func main() {
	err := errors.Join(errors.New("read failed"), errors.New("cleanup failed"))
	fmt.Println(err)
}
Output:
read failed
cleanup failed

func New

func New(text string) error

New returns an error with text and a stack captured at the call site.

func Unwrap

func Unwrap(err error) error

Unwrap returns err's single cause, using errors.Unwrap. It returns nil for errors that unwrap to multiple causes, including Join's results.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL