Documentation
¶
Overview ¶
Package errorhandling provides structured, user-friendly error reporting for command-line tools.
The ErrorHandler interface offers Check (route an error through the reporting pipeline), Fatal (report and exit), Error (non-terminating report), and Warn. Errors are rendered with any user-facing hints attached via cockroachdb/errors (WithHint/WithHintf, or the WithUserHint helpers here), plus an optional support-channel message supplied through HelpConfig.
An exit code can be attached to an error value with WithExitCode and is honoured when the error is reported at Fatal level, so the code that knows *why* something failed decides how the process exits.
Stack traces and error details are extracted from cockroachdb/errors and emitted only when the logger has debug enabled, giving rich diagnostics on demand without cluttering normal output.
The package carries no CLI-framework dependency. Where a parent command needs to print usage (an error wrapping ErrRunSubCommand), the caller supplies the printer through SetUsage — with Cobra, that is cmd.Usage.
Index ¶
- Constants
- Variables
- func ExitCode(err error) int
- func NewAssertionFailure(format string, args ...any) error
- func NewErrNotImplemented(issueURL string) error
- func WithExitCode(err error, code int) error
- func WithUserHint(err error, hint string) error
- func WithUserHintf(err error, format string, args ...any) error
- func WrapWithHint(err error, msg string, hint string) error
- type ErrorHandler
- type ExitFunc
- type HelpConfig
- type Option
- type StandardErrorHandler
- func (h *StandardErrorHandler) Check(err error, prefix string, level string)
- func (h *StandardErrorHandler) Error(err error, prefixes ...string)
- func (h *StandardErrorHandler) Fatal(err error, prefixes ...string)
- func (h *StandardErrorHandler) SetUsage(usage func() error)
- func (h *StandardErrorHandler) Warn(err error, prefixes ...string)
Examples ¶
Constants ¶
const ( LevelFatal = "fatal" // LevelFatalQuiet exits the process exactly like LevelFatal — honouring any // exit code attached via WithExitCode — but logs the message at debug rather // than error. It exists for expected, user-initiated terminations (e.g. a // SIGINT/SIGTERM interrupt) where the non-zero exit code is the signal and an // error-level log line would be noise. The message is still emitted at debug // so `--debug` continues to surface it. LevelFatalQuiet = "fatal-quiet" LevelError = "error" LevelWarn = "warn" KeyStacktrace = "stacktrace" KeyHelp = "help" KeyHints = "hints" KeyDetails = "details" )
Variables ¶
var ( ErrNotImplemented = errors.New("command not yet implemented") ErrRunSubCommand = errors.New("subcommand required") )
Functions ¶
func ExitCode ¶
ExitCode returns the exit code attached to err via WithExitCode. It returns 0 for a nil error and 1 for any error without an attached code. When codes are attached at multiple levels, the outermost (most recently applied) attachment wins, matching errors.As traversal order.
func NewAssertionFailure ¶
NewAssertionFailure creates an error denoting a programming bug.
func NewErrNotImplemented ¶
NewErrNotImplemented creates an unimplemented error with an optional issue tracker link.
func WithExitCode ¶
WithExitCode attaches a process exit code to err. The ErrorHandler's fatal path uses the attached code instead of the default 1, letting callers thread non-standard exit codes (for example the Unix 128+signum convention for signal-terminated runs) through the single exit path without a parallel os.Exit call site. Returns nil when err is nil.
func WithUserHint ¶
WithUserHint attaches a user-facing recovery suggestion to an error.
Example ¶
package main
import (
"fmt"
"github.com/cockroachdb/errors"
"gitlab.com/phpboyscout/go/errorhandling"
)
func main() {
err := errors.New("connection refused")
hinted := errorhandling.WithUserHint(err, "Check that the server is running and the port is correct")
fmt.Println(errors.FlattenHints(hinted))
}
Output: Check that the server is running and the port is correct
func WithUserHintf ¶
WithUserHintf attaches a formatted user-facing recovery suggestion.
func WrapWithHint ¶
WrapWithHint wraps an error with a message and attaches a user-facing hint.
Example ¶
package main
import (
"fmt"
"github.com/cockroachdb/errors"
"gitlab.com/phpboyscout/go/errorhandling"
)
func main() {
err := errors.New("file not found")
wrapped := errorhandling.WrapWithHint(err, "loading config", "Run 'mytool init' to create the config file")
fmt.Println(wrapped.Error())
fmt.Println(errors.FlattenHints(wrapped))
}
Output: loading config: file not found Run 'mytool init' to create the config file
Types ¶
type ErrorHandler ¶
type ErrorHandler interface {
Check(err error, prefix string, level string)
Fatal(err error, prefixes ...string)
Error(err error, prefixes ...string)
Warn(err error, prefixes ...string)
// SetUsage registers the function used to print usage when an error
// wrapping [ErrRunSubCommand] is reported. CLI frameworks supply their
// own printer — with Cobra, that is `SetUsage(cmd.Usage)`, typically set
// in each command's pre-run so the usage shown belongs to the command
// that actually failed.
SetUsage(usage func() error)
}
ErrorHandler defines the interface for structured error reporting. It formats errors with hints, stack traces, and help channel information, then routes them to the appropriate output (logger, writer, or exit).
func New ¶
func New(l *slog.Logger, help HelpConfig, opts ...Option) ErrorHandler
New creates an ErrorHandler with the given logger and help config. Options can override the exit function, output writer, or other defaults.
Example ¶
package main
import (
"gitlab.com/phpboyscout/go/errorhandling"
)
func main() {
handler := errorhandling.New(nil, nil)
_ = handler // Use handler.Check, handler.Error, handler.Fatal, handler.Warn
}
Output:
type ExitFunc ¶
type ExitFunc func(code int)
ExitFunc is the function called to terminate the process. Defaults to os.Exit. Override via WithExitFunc for testing.
type HelpConfig ¶
type HelpConfig interface {
SupportMessage() string
}
HelpConfig supplies contextual support information to attach to reported errors — typically "contact <team> via <channel>" for whatever support channel your organisation uses.
It is deliberately the only help-related type in this module: the extension point, with no opinion about where a team's support channel lives. Slack, Teams, an on-call rota, a wiki URL, or a message assembled from configuration are all just implementations you supply.
Returning an empty string suppresses the help output entirely, so an implementation can stay silent when it has nothing useful to say (for example when its channel is not configured yet):
type slackHelp struct{ team, channel string }
func (s slackHelp) SupportMessage() string {
if s.team == "" || s.channel == "" {
return "" // not configured — say nothing
}
return fmt.Sprintf("For assistance, contact %s via Slack channel %s", s.team, s.channel)
}
Pass an implementation to New; passing nil is valid and disables help output.
Example ¶
package main
import (
"fmt"
"gitlab.com/phpboyscout/go/errorhandling"
)
// slackHelp is an example HelpConfig implementation. The module ships only the
// interface, so an application defines whatever support channel it actually
// uses — Slack here, but equally Teams, an on-call rota, or a wiki URL.
type slackHelp struct {
Team string
Channel string
}
func (s slackHelp) SupportMessage() string {
if s.Team == "" || s.Channel == "" {
return ""
}
return fmt.Sprintf("For assistance, contact %s via Slack channel %s", s.Team, s.Channel)
}
func main() {
var help errorhandling.HelpConfig = slackHelp{
Team: "mycompany",
Channel: "#dev-support",
}
fmt.Println(help.SupportMessage())
}
Output: For assistance, contact mycompany via Slack channel #dev-support
type Option ¶
type Option func(*StandardErrorHandler)
Option is a functional option for configuring a StandardErrorHandler.
func WithExitFunc ¶
WithExitFunc allows injection of a custom exit handler (e.g. for testing).
func WithWriter ¶
WithWriter allows injection of a custom output writer.
type StandardErrorHandler ¶
type StandardErrorHandler struct {
Logger *slog.Logger
Help HelpConfig
Exit ExitFunc
Writer io.Writer
Usage func() error
}
StandardErrorHandler is the default ErrorHandler implementation. It extracts hints, details, and stack traces from cockroachdb/errors and formats them for terminal or structured output.
func (*StandardErrorHandler) Check ¶
func (h *StandardErrorHandler) Check(err error, prefix string, level string)
func (*StandardErrorHandler) Error ¶
func (h *StandardErrorHandler) Error(err error, prefixes ...string)
func (*StandardErrorHandler) Fatal ¶
func (h *StandardErrorHandler) Fatal(err error, prefixes ...string)
func (*StandardErrorHandler) SetUsage ¶
func (h *StandardErrorHandler) SetUsage(usage func() error)
func (*StandardErrorHandler) Warn ¶
func (h *StandardErrorHandler) Warn(err error, prefixes ...string)