Overview
Agones currently depends on github.com/pkg/errors v0.9.1 for error handling and wrapping. This package predates Go 1.13 (released 2019), which introduced native error wrapping and unwrapping via fmt.Errorf("...: %w", err), errors.Is, and errors.As.
pkg/errors is in maintenance mode — the author considers it feature-complete and defers to the stdlib for new work. Should we migrate to the modern stdlib approach?
This issue is a community discussion — please share your thoughts before we commit to any direction.
Current Usage
- 55 source files in
pkg/, cmd/, and sdks/go/ import github.com/pkg/errors
- Key functions in use:
pkg/errors function |
Approximate count |
Notes |
errors.Wrapf(err, "msg %s", arg) |
~118 |
Wraps with formatted message + stack trace |
errors.Errorf("msg %s", arg) |
~118 |
Like fmt.Errorf but with stack trace |
errors.Wrap(err, "msg") |
~59 |
Wraps with message + stack trace |
errors.New("msg") |
~58 |
Like stdlib errors.New but with stack trace |
errors.WithStack(err) |
~4 |
Adds stack trace to an existing error |
errors.Cause(err) |
~3 |
Unwraps to the root cause |
errors.StackTrace interface |
~1 |
Used in pkg/util/runtime/runtime.go for logging |
The stack trace interface is used in pkg/util/runtime/runtime.go to extract and log stack traces from errors, and errors.Cause is used in pkg/util/workerqueue/workerqueue.go and pkg/gameserverallocations/allocator.go to inspect wrapped Kubernetes conflict errors.
Pros of Migrating to stdlib
- One fewer dependency — removes
github.com/pkg/errors from go.mod/go.sum and the vendor/ tree
- Idiomatic modern Go — stdlib error wrapping (
%w) is now the community standard; contributors familiar with modern Go won't need to learn pkg/errors idioms
- Future-proof —
pkg/errors is in maintenance mode; stdlib errors continue to evolve
- Simpler unwrapping —
errors.Is / errors.As work correctly with %w-wrapped errors and are already used in the codebase
- No import alias confusion — currently some files alias the errors import which can be confusing
Cons of Migrating to stdlib
- Loss of automatic stack traces — this is the biggest downside.
pkg/errors captures a stack trace at the point Wrap/New/Errorf is called. The stdlib has no equivalent. We currently log these stack traces in pkg/util/runtime/runtime.go to help diagnose panics and unexpected errors
errors.Cause → errors.Unwrap is not 1:1 — errors.Cause walks the entire error chain to the root; errors.Unwrap only unwraps one level. errors.Is/errors.As handle chain traversal but require a different call pattern
- Large refactor — ~55 files need mechanical changes, with careful review required wherever
Cause or stack traces are used
- SDK impact —
sdks/go/ is a public-facing SDK; this is a non-breaking change (errors still implement the error interface), but it changes observable behaviour for anyone inspecting error strings or types
Options
- Migrate fully to stdlib (
errors + fmt.Errorf) — accept the loss of stack traces, or replace the stack-trace logging in runtime.go with runtime/debug.Stack() at the panic/log site
- Migrate to stdlib + thin stack trace helper — keep a small internal utility only where stack traces are genuinely needed, or research whether a lightweight third-party library better fits our needs than
pkg/errors
- Stay on
pkg/errors — it still works fine and the migration cost may not be worth it
- Gradual / file-by-file migration — new code uses stdlib; existing code migrates opportunistically
Questions for the Community
- How much do we rely on the stack traces that
pkg/errors captures? Are they regularly useful in debugging?
- Is there a preference for option 1, 2, 3, or 4 above?
- For option 2, are there lightweight stack trace or error extension libraries worth evaluating?
- Is anyone willing to lead or contribute to this migration if we decide to go ahead?
Please comment below with your thoughts!
Overview
Agones currently depends on
github.com/pkg/errorsv0.9.1 for error handling and wrapping. This package predates Go 1.13 (released 2019), which introduced native error wrapping and unwrapping viafmt.Errorf("...: %w", err),errors.Is, anderrors.As.pkg/errorsis in maintenance mode — the author considers it feature-complete and defers to the stdlib for new work. Should we migrate to the modern stdlib approach?This issue is a community discussion — please share your thoughts before we commit to any direction.
Current Usage
pkg/,cmd/, andsdks/go/importgithub.com/pkg/errorspkg/errorsfunctionerrors.Wrapf(err, "msg %s", arg)errors.Errorf("msg %s", arg)fmt.Errorfbut with stack traceerrors.Wrap(err, "msg")errors.New("msg")errors.Newbut with stack traceerrors.WithStack(err)errors.Cause(err)errors.StackTraceinterfacepkg/util/runtime/runtime.gofor loggingThe stack trace interface is used in
pkg/util/runtime/runtime.goto extract and log stack traces from errors, anderrors.Causeis used inpkg/util/workerqueue/workerqueue.goandpkg/gameserverallocations/allocator.goto inspect wrapped Kubernetes conflict errors.Pros of Migrating to stdlib
github.com/pkg/errorsfromgo.mod/go.sumand thevendor/tree%w) is now the community standard; contributors familiar with modern Go won't need to learnpkg/errorsidiomspkg/errorsis in maintenance mode; stdlib errors continue to evolveerrors.Is/errors.Aswork correctly with%w-wrapped errors and are already used in the codebaseCons of Migrating to stdlib
pkg/errorscaptures a stack trace at the pointWrap/New/Errorfis called. The stdlib has no equivalent. We currently log these stack traces inpkg/util/runtime/runtime.goto help diagnose panics and unexpected errorserrors.Cause→errors.Unwrapis not 1:1 —errors.Causewalks the entire error chain to the root;errors.Unwraponly unwraps one level.errors.Is/errors.Ashandle chain traversal but require a different call patternCauseor stack traces are usedsdks/go/is a public-facing SDK; this is a non-breaking change (errors still implement theerrorinterface), but it changes observable behaviour for anyone inspecting error strings or typesOptions
errors+fmt.Errorf) — accept the loss of stack traces, or replace the stack-trace logging inruntime.gowithruntime/debug.Stack()at the panic/log sitepkg/errorspkg/errors— it still works fine and the migration cost may not be worth itQuestions for the Community
pkg/errorscaptures? Are they regularly useful in debugging?Please comment below with your thoughts!