clierror

package
v0.0.0-...-0cfb28e Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

README

CLI Error Handling Package

pkg/clierror provides standard error handling infrastructure for CLI entry points in the commitgraph project.

Purpose

This package addresses a common issue across CLI tools: ensuring that:

  1. Panics are caught and logged with stack traces before exit
  2. Errors are logged consistently and exit codes are appropriate
  3. Main functions never return normally (always call os.Exit())
  4. Errors are wrapped with structured context for better debugging
  5. Exit codes follow standard conventions based on error categories

Usage

Basic pattern for all CLI entry points:

package main

import (
    "github.com/jedarden/commitgraph/pkg/clierror"
)

func main() {
    clierror.Run(run)
}

func run() error {
    // Your CLI logic here
    // Return nil on success
    // Return error on failure
    return nil
}

Features

Panic Recovery

If your run() function panics, clierror.Run will:

  1. Recover from the panic
  2. Log the panic value
  3. Log the full stack trace
  4. Exit with code 1
Error Handling

If your run() function returns an error, clierror.Run will:

  1. Log the error message
  2. Exit with the appropriate code (determined by error category)
Error Categories and Exit Codes

The package provides standard error categories with default exit codes following common CLI conventions:

Category Exit Code Usage
CategoryUsage 2 Command-line argument/flag errors
CategoryInput 3 File validation, data parsing errors
CategoryNetwork 4 Connection failures, timeouts
CategoryPermission 5 Authorization/access control errors
CategoryInternal 70 Bugs, unexpected errors (should not occur)
CategoryTransient 75 Temporary failures (might succeed on retry)

Error Wrapping Patterns

Basic Wrapping with Context
func run() error {
    data, err := os.ReadFile("config.json")
    if err != nil {
        return clierror.NewInput(
            "failed to read configuration file",
            err,
        )
    }
    // ... process data
    return nil
}
Wrapping with Additional Context
func run() error {
    data, err := os.ReadFile(filepath)
    if err != nil {
        return clierror.NewInputWithContext(
            "failed to read file",
            filepath,
            err,
        )
    }
    // ... process data
    return nil
}
Convenience Wrappers

The package provides convenience functions that only wrap if the error is non-nil:

func run() error {
    data, err := os.ReadFile("input.json")
    if err != nil {
        return clierror.WrapInput("failed to read input file", err)
    }

    var config Config
    if err := json.Unmarshal(data, &config); err != nil {
        return clierror.WrapInput("failed to parse input JSON", err)
    }

    // ... process config
    return nil
}
Network Error Handling
func run() error {
    resp, err := http.Get(url)
    if err != nil {
        return clierror.WrapNetwork("failed to fetch data", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        return clierror.NewNetwork(
            fmt.Sprintf("server returned error status: %d", resp.StatusCode),
            fmt.Errorf("HTTP %d", resp.StatusCode),
        )
    }
    // ... process response
    return nil
}
Usage Error Handling
func run() error {
    if *inputPath == "" {
        return clierror.NewUsage(
            "missing required --input flag",
            fmt.Errorf("no input path specified"),
        )
    }
    // ... process
    return nil
}
All Conditional Wrappers

The conditional wrappers are useful when you want to add context but only if an error actually occurred:

func run() error {
    // Usage errors
    if err := validateFlags(); err != nil {
        return clierror.WrapUsage("flag validation failed", err)
    }

    // Input errors
    if err := parseInput(data); err != nil {
        return clierror.WrapInput("input parsing failed", err)
    }

    // Network errors
    if err := fetchRemoteData(); err != nil {
        return clierror.WrapNetwork("remote fetch failed", err)
    }

    // Permission errors
    if err := checkAccess(); err != nil {
        return clierror.WrapPermission("access check failed", err)
    }

    // Internal errors (bugs)
    if err := internalInvariantCheck(); err != nil {
        return clierror.WrapInternal("invariant violation", err)
    }

    // Transient errors (retryable)
    if err := attemptOperation(); err != nil {
        return clierror.WrapTransient("temporary failure", err)
    }

    return nil
}
Custom Exit Codes

You can override the default exit code for any category:

func run() error {
    if !isValid() {
        return clierror.NewWrapWithExitCode(
            clierror.CategoryInput,
            "validation failed",
            10, // Custom exit code
            fmt.Errorf("invalid data format"),
        )
    }
    return nil
}

Error Types

WrappedError

The primary error type that provides structured context:

type WrappedError struct {
    Category         ErrorCategory  // Error classification
    Message          string         // Human-readable description
    Context          string         // Additional context
    Err              error          // Underlying error
    ExitCodeOverride int            // Custom exit code
}
ExitCodeError (Legacy)

Legacy error type for simple exit code wrapping:

type ExitCodeError struct {
    ExitCode int
    Err      error
}

Helper Functions

Category-Specific Constructors
  • NewUsage(message, err) - Usage/argument errors (exit code 2)
  • NewInput(message, err) - Input/data errors (exit code 3)
  • NewInputWithContext(message, context, err) - Input errors with context
  • NewNetwork(message, err) - Network errors (exit code 4)
  • NewPermission(message, err) - Permission errors (exit code 5)
  • NewInternal(message, err) - Internal errors (exit code 70)
  • NewTransient(message, err) - Transient errors (exit code 75)
Conditional Wrappers

These functions only wrap if the error is non-nil (return nil if err == nil):

  • WrapInput(message, err) - Conditional input error wrapping
  • WrapInputWithContext(message, context, err) - Conditional with context
  • WrapNetwork(message, err) - Conditional network error wrapping
  • WrapUsage(message, err) - Conditional usage error wrapping
  • WrapPermission(message, err) - Conditional permission error wrapping
  • WrapInternal(message, err) - Conditional internal error wrapping
  • WrapTransient(message, err) - Conditional transient error wrapping
General Wrappers
  • NewWrap(category, message, err) - Generic wrapped error
  • NewWrapWithContext(category, message, context, err) - With context
  • NewWrapWithExitCode(category, message, exitCode, err) - Custom exit code
Utility Functions
  • GetExitCode(err) - Extract exit code from any error type

Testing

The package is designed to work with os.Exit(), which makes direct testing challenging. For testing CLI tools:

  1. Extract the main logic into a separate run() function
  2. Test run() directly without calling clierror.Run
  3. clierror.Run is only for the actual main function
// In your test file
func TestRun(t *testing.T) {
    // Test the run function directly
    err := run()
    if err != nil {
        t.Errorf("run() failed: %v", err)
    }
}

Migration Guide

Before (no error catching):
func main() {
    if err := doSomething(); err != nil {
        log.Fatalf("Error: %v", err)
    }
}
After (with error catching):
func main() {
    clierror.Run(run)
}

func run() error {
    if err := doSomething(); err != nil {
        return clierror.WrapInput("operation failed", err)
    }
    return nil
}
Before (basic error wrapping):
func run() error {
    data, err := os.ReadFile("config.json")
    if err != nil {
        return fmt.Errorf("failed to read config: %w", err)
    }
    // ... process
    return nil
}
After (structured error wrapping):
func run() error {
    data, err := os.ReadFile("config.json")
    if err != nil {
        return clierror.NewInputWithContext(
            "failed to read configuration",
            "config.json",
            err,
        )
    }
    // ... process
    return nil
}

Complete Example

package main

import (
    "encoding/json"
    "flag"
    "fmt"
    "os"

    "github.com/jedarden/commitgraph/pkg/clierror"
)

func main() {
    clierror.Run(run)
}

func run() error {
    inputPath := flag.String("input", "", "Path to input file")
    flag.Parse()

    // Usage error handling
    if *inputPath == "" {
        return clierror.NewUsage(
            "missing required flag",
            fmt.Errorf("--input is required"),
        )
    }

    // Input reading with context
    data, err := os.ReadFile(*inputPath)
    if err != nil {
        return clierror.NewInputWithContext(
            "failed to read input file",
            *inputPath,
            err,
        )
    }

    // Input parsing
    var config Config
    if err := json.Unmarshal(data, &config); err != nil {
        return clierror.WrapInput("failed to parse input JSON", err)
    }

    // Network operation (if needed)
    if err := processData(&config); err != nil {
        return clierror.WrapNetwork("failed to process data", err)
    }

    fmt.Println("Processing complete!")
    return nil
}

Comprehensive Examples

The file examples.go contains 15 comprehensive examples covering common CLI error handling patterns:

  1. Basic usage error handling - Flag and argument validation
  2. File reading with context - Including file paths in error messages
  3. JSON parsing - Structured data parsing errors
  4. Network operations - HTTP requests and connection failures
  5. Database connections - Multiple error types in one operation
  6. Directory walking - Error accumulation during batch processing
  7. Conditional wrapping - Only wrapping when error occurs
  8. Custom exit codes - Overriding default exit codes
  9. Internal errors - Bug/invariant violations
  10. Transient errors - Retryable temporary failures
  11. Multi-step operations - Layered error handling
  12. Complete run() function - Full CLI structure
  13. Error accumulation - Collecting multiple errors
  14. Permission handling - Access control errors
  15. Panic-safe processing - Working with panic recovery

Use these examples as reference patterns when implementing or refactoring CLI commands.

# View the examples
cat pkg/clierror/examples.go

Quick Reference: Common Patterns

When to use each error category
Scenario Category Exit Code Function
Missing/invalid flags CategoryUsage 2 NewUsage, WrapUsage
File read/write errors CategoryInput 3 NewInput, WrapInput, NewInputWithContext
JSON parse errors CategoryInput 3 WrapInput
Connection failures CategoryNetwork 4 NewNetwork, WrapNetwork
Permission denied CategoryPermission 5 NewPermission, WrapPermission
Bugs/invariant violations CategoryInternal 70 NewInternal, WrapInternal
Temporary failures CategoryTransient 75 NewTransient, WrapTransient
Pattern: Include context when possible
// ❌ Bad: No context
return clierror.NewInput("file read failed", err)

// ✅ Good: Includes which file
return clierror.NewInputWithContext("file read failed", filepath, err)
Pattern: Use conditional wrappers
// These only wrap if err != nil (return nil if err is nil)
return clierror.WrapInput("failed to parse", err)
return clierror.WrapNetwork("connection failed", err)

See Also

  • pkg/clierror/examples.go - 15 comprehensive error wrapping examples
  • pkg/warmstart/error.go - Similar error handling patterns for warmstart parsing
  • Go's standard errors package for error wrapping
  • Unix/SysExit conventions for exit code meanings

Documentation

Overview

Package clierror provides reusable error catching templates and helpers.

This file contains defer/recover templates that wrap panics and errors in the standard error structure and map them to appropriate exit codes.

Usage Examples:

Simple panic recovery:

func myFunction() {
    defer clierror.RecoverPanic()
    // ... code that might panic
}

Panic recovery with custom handler:

func myFunction() {
    defer clierror.RecoverPanicWithHandler(func(r interface{}) error {
        return clierror.NewInternal("panic occurred", fmt.Errorf("%v", r))
    })
    // ... code that might panic
}

Comprehensive error catching in main():

func main() {
    clierror.RunSafe(run)
}

func run() error {
    // Your main logic here
    return nil
}

Package clierror provides utilities for CLI error handling, including commit SHA retrieval.

Package clierror provides standard error handling infrastructure for CLI entry points.

This package provides utilities for catching panics, wrapping errors with context, error categorization, and ensuring clean error propagation from CLI main functions without panics reaching the runtime.

Usage:

func main() {
    clierror.Run(run)
}

func run() error {
    // Your main logic here
    return nil
}

Package clierror provides standard error handling infrastructure for CLI entry points.

This file contains comprehensive examples of error wrapping patterns that can be used as reference when implementing or refactoring CLI commands.

Index

Examples

Constants

This section is empty.

Variables

DefaultExitCodes maps error categories to their default exit codes. These follow common CLI conventions: - 1: General errors - 2: Usage errors (like getopt) - 3: Input/data errors - 4: Network errors - 5: Permission errors - 70: Internal software errors (like sysexits.h) - 75: Transient/temporary errors

Functions

func CatchPanic

func CatchPanic(fn func()) (err error)

CatchPanic is a generic panic catching template that returns an error if a panic occurred, or nil if the function completed successfully.

This is useful for inline panic catching without defer statements.

Example:

if err := clierror.CatchPanic(func() {
    // Code that might panic
    mightPanic()
}); err != nil {
    log.Printf("Caught panic: %v", err)
}

func CleanupAndRecover

func CleanupAndRecover(errPtr *error, cleanup func())

CleanupAndRecover combines cleanup execution with panic recovery. It ensures cleanup runs even if a panic occurs, then converts panic to error.

Example:

func process(data []byte) (err error) {
    file, err := os.Open("data.txt")
    if err != nil {
        return err
    }

    defer clierror.CleanupAndRecover(&err, func() {
        file.Close()
    })

    // ... process file, potential panic here
    return nil
}

func DeferRecover

func DeferRecover(errPtr *error)

DeferRecover is a template function for deferred error recovery. It's useful when you need to perform cleanup and error handling together.

Example:

func process(data []byte) (err error) {
    defer clierror.DeferRecover(&err)
    file, err := os.Open("data.txt")
    if err != nil {
        return NewInputWithContext("failed to open file", "data.txt", err)
    }
    defer file.Close()
    // ... process file
    return nil
}

func GetCommitSHA

func GetCommitSHA() string

GetCommitSHA retrieves the commit SHA from the following sources in order: 1. The .needle-predispatch-sha file in the repository root 2. git rev-parse HEAD command (fallback) 3. Empty string if neither method succeeds

This function is called by entry points to obtain the commit SHA that should be threaded through all intermediate function calls to error constructors.

Returns the commit SHA as a string (40-character hexadecimal) or empty string if unavailable.

func GetExitCode

func GetExitCode(err error) int

GetExitCode extracts the appropriate exit code from an error. For WrappedError, it uses the error's ExitCode() method. For ExitCodeError, it uses the embedded ExitCode field. For other errors, it returns 1.

func Must

func Must(fn func() error)

Must executes a function and panics with an internal error if it returns an error. This is useful for initialization code that must succeed.

Example:

func init() {
    clierror.Must(loadConfig())
    clierror.Must(connectDatabase())
}

func loadConfig() error {
    // Load configuration
    return nil
}
Example
// Initialization that must succeed
initialize := func() error {
	return nil
}

// Use in init():
// func init() {
//     clierror.Must(initialize())
// }
_ = initialize

func MustValue

func MustValue[T any](fn func() (T, error)) T

MustValue executes a function that returns a value and an error. It panics with an internal error if the function returns an error, otherwise returns the value.

Example:

func main() {
    config := clierror.MustValue(loadConfig)
    _ = config
}

func loadConfig() (*Config, error) {
    cfg, err := readConfig()
    if err != nil {
        return nil, err
    }
    return cfg, nil
}

func RecoverAndReturn

func RecoverAndReturn(errPtr *error)

RecoverAndReturn is a defer/recover template for functions that return errors. It catches panics, converts them to errors, and assigns them to a pointer.

This pattern is useful when you want a function to return errors instead of panicking, making error handling more explicit.

Example:

func process(data []byte) (err error) {
    defer clierror.RecoverAndReturn(&err)
    var result interface{}
    if err := json.Unmarshal(data, &result); err != nil {
        return WrapInput("JSON parse failed", err)
    }
    _ = result
    return nil
}
Example
// Converting panics to returned errors
parseJSON := func(data []byte) (err error) {
	defer RecoverAndReturn(&err)
	var result map[string]interface{}
	if err := json.Unmarshal(data, &result); err != nil {
		panic(fmt.Sprintf("JSON parse failed: %v", err))
	}
	return nil
}

_ = parseJSON([]byte(`{"key": "value"}`))

func RecoverPanic

func RecoverPanic()

RecoverPanic is a simple defer/recover template that catches panics, logs them with stack trace, and converts them to internal errors.

This function should be used as a defer statement at the beginning of functions that might panic. It never returns normally - it panics again with a WrappedError containing the original panic value.

Example:

func process(data []byte) {
    defer clierror.RecoverPanic()
    var result interface{}
    if err := json.Unmarshal(data, &result); err != nil {
        panic(fmt.Sprintf("JSON parse failed: %v", err))
    }
    _ = result
}
Example

Example usage tests (documentation through tests)

// Simple panic recovery in a function
processData := func(data []byte) {
	defer RecoverPanic()
	// Code that might panic
	if len(data) == 0 {
		panic("no data to process")
	}
}

processData([]byte{1, 2, 3})

func RecoverPanicWithHandler

func RecoverPanicWithHandler(handler func(r interface{}) error)

RecoverPanicWithHandler is a defer/recover template that catches panics and passes them to a custom handler function for conversion to errors.

The handler function receives the panic value and should return an error (typically a WrappedError). If the handler returns nil, no panic is re-raised. Otherwise, the returned error is used as the panic value.

Example:

func process(data []byte) {
    defer clierror.RecoverPanicWithHandler(func(r interface{}) error {
        errMsg := fmt.Sprintf("processing failed: %v", r)
        return clierror.NewInput("data processing error", fmt.Errorf(errMsg))
    })
    // ... code that might panic
}

func Run

func Run(fn func() error)

Run executes a function, catching panics and handling errors cleanly.

If fn returns an error, Run prints it to stderr and exits with the appropriate code (determined by the error type: 1 for general errors, or custom codes from ExitCodeError/WrappedError).

If fn panics, Run recovers, logs the panic with stack trace, and exits with code 1.

Run never returns - it always calls os.Exit().

func RunSafe

func RunSafe(fn func() error)

RunSafe executes a function with comprehensive panic and error handling. It catches panics, handles errors, and exits with appropriate codes.

This is the main entry point template for CLI applications. It combines panic recovery with error handling and exit code mapping.

If fn panics, RunSafe logs the panic with stack trace and exits with code 70. If fn returns an error, RunSafe prints the error and exits with the appropriate code based on the error type. If fn succeeds, RunSafe exits with code 0.

Example:

func main() {
    clierror.RunSafe(run)
}

func run() error {
    // Your main logic here
    if *inputPath == "" {
        return NewUsage("missing required flag",
            errors.New("--input is required"))
    }
    return nil
}
Example
// Main entry point with panic and error handling
run := func() error {
	// Your main logic here
	return nil
}

// Use in main():
// func main() {
//     clierror.RunSafe(run)
// }
_ = run

func RunSafeWithDefault

func RunSafeWithDefault(fn func() error, defaultExitCode int)

RunSafeWithDefault executes a function with panic/error handling and a default exit code for unspecified errors.

This is similar to RunSafe but allows specifying a custom exit code for general errors (instead of the default 1).

Example:

func main() {
    clierror.RunSafeWithDefault(run, 2) // Use exit code 2 for general errors
}

func RunWithExitCode

func RunWithExitCode(fn func() error, successCode int)

RunWithExitCode executes a function, catching panics and handling errors cleanly.

If fn returns an error, RunWithExitCode prints it to stderr and exits with the appropriate code (determined by the error type: 1 for general errors, or custom codes from ExitCodeError/WrappedError).

If fn panics, RunWithExitCode recovers, logs the panic with stack trace, and exits with code 1.

If fn returns successfully, RunWithExitCode exits with the provided success code.

RunWithExitCode never returns - it always calls os.Exit().

func Safe

func Safe(fn func() error) (err error)

Safe executes a function and returns any error (or panic converted to error). This ensures a function never panics - all panics are converted to errors.

Example:

if err := clierror.Safe(func() error {
    // Code that might panic or return an error
    return process(data)
}); err != nil {
    log.Printf("Operation failed: %v", err)
}
Example
// Ensure a function never panics
result := Safe(func() error {
	// Code that might panic or return an error
	return nil
})

_ = result

func WithErrorRecovery

func WithErrorRecovery(fn func() error) func() error

WithErrorRecovery is a higher-order function that wraps a function with panic recovery. The wrapped function will convert any panic to an error.

This is useful for creating panic-safe function wrappers.

Example:

var safeProcess = clierror.WithErrorRecovery(process)

err := safeProcess(data)
if err != nil {
    log.Printf("Process failed: %v", err)
}

func WrapInput

func WrapInput(message string, err error) error

WrapInput is a convenience function that wraps an error with input category only if the error is non-nil. Returns nil if err is nil.

func WrapInputWithContext

func WrapInputWithContext(message, context string, err error) error

WrapInputWithContext is a convenience function that wraps an error with input category and context only if the error is non-nil.

func WrapInternal

func WrapInternal(message string, err error) error

WrapInternal is a convenience function that wraps an error with internal category only if the error is non-nil.

func WrapNetwork

func WrapNetwork(message string, err error) error

WrapNetwork is a convenience function that wraps an error with network category only if the error is non-nil.

func WrapPermission

func WrapPermission(message string, err error) error

WrapPermission is a convenience function that wraps an error with permission category only if the error is non-nil.

func WrapTransient

func WrapTransient(message string, err error) error

WrapTransient is a convenience function that wraps an error with transient category only if the error is non-nil.

func WrapUsage

func WrapUsage(message string, err error) error

WrapUsage is a convenience function that wraps an error with usage category only if the error is non-nil.

Types

type ErrorCategory

type ErrorCategory string

ErrorCategory represents a classification of errors for consistent exit code mapping.

const (
	// CategoryUsage indicates command-line usage errors (invalid flags, missing arguments, etc.)
	CategoryUsage ErrorCategory = "usage"
	// CategoryInput indicates input validation or data errors (invalid files, malformed data, etc.)
	CategoryInput ErrorCategory = "input"
	// CategoryNetwork indicates network-related errors (connection failures, timeouts, etc.)
	CategoryNetwork ErrorCategory = "network"
	// CategoryPermission indicates permission or authorization errors
	CategoryPermission ErrorCategory = "permission"
	// CategoryInternal indicates internal errors that should not occur (bugs, panics, etc.)
	CategoryInternal ErrorCategory = "internal"
	// CategoryTransient indicates transient errors that might succeed on retry
	CategoryTransient ErrorCategory = "transient"
)

type ExitCodeError

type ExitCodeError struct {
	// ExitCode is the code to exit with (defaults to 1 if 0).
	ExitCode int

	// Err is the underlying error.
	Err error
}

ExitCodeError is an error that carries a specific exit code.

func NewExitCodeError

func NewExitCodeError(code int, err error) *ExitCodeError

NewExitCodeError creates a new ExitCodeError with the given code and underlying error.

func (*ExitCodeError) Error

func (e *ExitCodeError) Error() string

Error implements the error interface.

func (*ExitCodeError) Unwrap

func (e *ExitCodeError) Unwrap() error

Unwrap returns the underlying error for errors.Is/As compatibility.

type WrappedError

type WrappedError struct {
	// Category classifies the error type for exit code mapping
	Category ErrorCategory

	// Message is a human-readable description of what operation failed
	Message string

	// Context provides additional context about the error
	Context string

	// Err is the underlying error (may be nil for standalone errors)
	Err error

	// ExitCodeOverride allows overriding the default exit code for this category
	ExitCodeOverride int
}

WrappedError provides rich context wrapping for errors with categorization. It supports standard error wrapping patterns while adding structured context for better error messages and exit code mapping.

func NewInput

func NewInput(message string, err error) *WrappedError

NewInput creates a new input error (exit code 3 by default). Use this for file validation, data parsing, and input errors.

func NewInputWithContext

func NewInputWithContext(message, context string, err error) *WrappedError

NewInputWithContext creates a new input error with additional context. Use this when you need to specify which file or input source failed.

func NewInternal

func NewInternal(message string, err error) *WrappedError

NewInternal creates a new internal error (exit code 70 by default). Use this for bugs and errors that should never occur.

func NewNetwork

func NewNetwork(message string, err error) *WrappedError

NewNetwork creates a new network error (exit code 4 by default). Use this for connection failures, timeouts, and HTTP errors.

func NewPermission

func NewPermission(message string, err error) *WrappedError

NewPermission creates a new permission error (exit code 5 by default). Use this for authorization and access control errors.

func NewTransient

func NewTransient(message string, err error) *WrappedError

NewTransient creates a new transient error (exit code 75 by default). Use this for temporary failures that might succeed on retry.

func NewUsage

func NewUsage(message string, err error) *WrappedError

NewUsage creates a new usage error (exit code 2 by default). Use this for command-line argument and flag errors.

func NewWrap

func NewWrap(category ErrorCategory, message string, err error) *WrappedError

NewWrap creates a new WrappedError with the given category, message, and underlying error. This is the most common wrapping function for adding context to errors.

func NewWrapWithContext

func NewWrapWithContext(category ErrorCategory, message, context string, err error) *WrappedError

NewWrapWithContext creates a new WrappedError with additional context string. Use this when you need to provide extra context about what failed.

func NewWrapWithExitCode

func NewWrapWithExitCode(category ErrorCategory, message string, exitCode int, err error) *WrappedError

NewWrapWithExitCode creates a new WrappedError with a custom exit code. Use this when you need to override the default exit code for a category.

func (*WrappedError) Error

func (e *WrappedError) Error() string

Error implements the error interface, providing a formatted error message.

func (*WrappedError) ExitCode

func (e *WrappedError) ExitCode() int

ExitCode returns the appropriate exit code for this error. It uses ExitCodeOverride if set, otherwise looks up the default for the category.

func (*WrappedError) Unwrap

func (e *WrappedError) Unwrap() error

Unwrap returns the underlying error for errors.Is/As compatibility.

Jump to

Keyboard shortcuts

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