Skip to content

Discussion: Migrate from github.com/pkg/errors to stdlib errors package? #4510

@markmandel

Description

@markmandel

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-proofpkg/errors is in maintenance mode; stdlib errors continue to evolve
  • Simpler unwrappingerrors.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.Causeerrors.Unwrap is not 1:1errors.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 impactsdks/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

  1. 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
  2. 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
  3. Stay on pkg/errors — it still works fine and the migration cost may not be worth it
  4. 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/cleanupRefactoring code, fixing up documentation, etckind/designProposal discussing new features / fixes and how they should be implemented

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions