A lightweight Go errors package with stack tracing and structured fields.
- ✅ Standard library compatible: Drop-in replacement for
errors
package - 🔍 Automatic stack tracing: Captures call stack when errors are created
- 📊 Structured fields: Add key-value pairs with
With()
method - 🎨 Multiple formats: Text, JSON, and colorized output
- 🔗 Error wrapping: Full support for
%w
verb and error chains - ⚡ High performance: Efficient implementation with object pooling
- 🔌 Logs integration: Native support for github.com/yanun0323/logs package
⚠️ Caution: usingfmt.Errorf
to wrap errors is not compatible witherrors.Is
anderrors.As
methods.
go get github.com/yanun0323/errors
- Go 1.21+
import "github.com/yanun0323/errors"
// Create error with fields
err := errors.New("connection failed").
With(
"host", "localhost",
"port", 5432,
)
// Error wrapping
wrapped := errors.Errorf("database error: %w", err)
// or
wrapped = errors.Wrap(err)
wrapped = errors.Wrap(err, "database error")
wrapped = errors.Wrapf(err, "database %s error", database)
// Format output
println(err.Error()) // Basic message
errors.Format(err) // Text with stack trace
errors.FormatJson(err) // JSON text with stack trace
errors.FormatColorized(err) // Colorized text with stack trace
fmt.Printf("%s\n", err) // Basic message
fmt.Printf("%v\n", err) // Formatted text with stack trace
fmt.Printf("%+v\n", err) // Formatted & colorized text with stack trace
fmt.Printf("%#v\n", err) // JSON text with stack trace
// Error Template
errTmp := errors.NewTemplate("service", "user-service")
errTmpDB := errTmp.With("component", "database")
err1 := errTmpDB.New("connection established")
err2 := errTmpDB.Errorf("query timeout after %d seconds", 30)
err3 := errTmpDB.Wrapf(originalErr, "database operation %d times", 3)
// Logs Package Integration
import "github.com/yanun0323/logs"
logs.WithError(err1).Error("connection established")
logs.WithError(err2).Error("query timeout")
logs.WithError(err3).Error("database operation")
errors.New(text string) Error
errors.Errorf(format string, args ...any) Error
errors.Wrap(err error, args ...any) Error
errors.Wrapf(err error, format string, args ...any) Error
Create error templates with predefined attributes for reuse:
errors.NewTemplate(args ...any) Template
template.With(args ...any) Template // Add more attributes (chainable)
template.New(text string) Error // Create error with template attributes
template.Wrap(err error, args ...any) Error // Wrap error with template attributes
template.Wrapf(err error, format string, args ...any) Error // Wrap error with formatted message
template.Errorf(format string, args ...any) Error // Create formatted error
err.Error() string // Standard error message
err.With(args ...any) Error // Add fields (chainable)
errors.Is(err, target error) bool
errors.As(err error, target any) bool
errors.Unwrap(err error) error
errors.Format(err error) string // Text with stack trace
errors.FormatColorized(err error) string // Colorized text with stack trace
errors.FormatJson(err error) string // JSON text with stack trace
This package interoperates with the github.com/yanun0323/logs package.
logger := logs.Default()
err := errors.New("database connection failed").
With(
"host", "localhost",
"port", 5432,
)
logger.WithError(err).Error("Operation error")
When using with the logs
package, errors created by this package can be directly passed to log functions and will automatically extract structured fields and stack traces.
err := errors.New("validation failed").
With(
"field", "email",
"value", "invalid@",
"rule", "email_format",
)
original := errors.New("network timeout")
wrapped := errors.Errorf("failed to fetch user: %w", original)
// Create a template with common attributes
errTmp := errors.NewTemplate("service", "user-service", "version", "1.0.0")
// Add more attributes to the template
errTmpDB := errTmp.With("component", "database", "host", "localhost")
// Create errors using the template
err1 := errTmpDB.New("connection failed")
err2 := errTmpDB.Errorf("query timeout after %d seconds", 30)
err3 := errTmpDB.Wrap(originalErr, "database operation failed")
err := errors.New("process failed").With("pid", 1234)
fmt.Printf("%#v\n", err)
// Outputs structured JSON with message, fields, and stack trace
import (
"github.com/yanun0323/errors"
"github.com/yanun0323/logs"
)
// Create an error with structured fields
err := errors.New("database connection failed").
With(
"host", "localhost",
"port", 5432,
"timeout", "30s",
)
// Pass directly to logs package
logs.Error("Operation failed", err)
// The logs package will automatically extract:
// - Error message
// - Structured attributes (host, port, timeout)
// - Stack trace information
error:
process user, err: user validation failed, err: root: user not found
cause:
user not found
field:
validateUser:
user_id: 0
table: users
func: validateUser
processUser:
func: processUser
handleRequest:
host: db.example.com
port: 5432
timeout: 30s
func: handleRequest
stack:
validateUser:
/Users/Shared/Project/personal/go/errors/example/main.go:58 in validateUser
processUser:
/Users/Shared/Project/personal/go/errors/example/main.go:47 in processUser
handleRequest:
/Users/Shared/Project/personal/go/errors/example/main.go:34 in handleRequest
main:
/Users/Shared/Project/personal/go/errors/example/main.go:18 in main
{
"cause": "user not found",
"error": "process user, err: user validation failed, err: root: user not found",
"field": [
{
"function": "validateUser",
"key": "user_id",
"value": 0
}
// ...
],
"stack": [
{
"file": "/Users/Shared/Project/personal/go/errors/example/main.go",
"function": "validateUser",
"line": "58"
}
// ...
]
}
fmt.Errorf
Use
errors.New
orerrors.Errorf
instead for proper compatibility witherrors.Is
anderrors.As
.