xerrors

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Dec 2, 2025 License: MIT Imports: 9 Imported by: 0

README

x-errors: Structured Error Handling for Go

Go Gopher with error handling
x-errors — structured, type-safe error handling for Go applications.
Go beyond simple error strings with semantic error classification, rich metadata, and templated messages!

Go Reference MIT License Package Version GoReportCard GitLab CI/CD Pipeline Test Coverage
🎯 Transform your error handling from simple strings to rich, structured data that powers observability, debugging, and user experiences.

✨ Why x-errors?

Go's built-in error handling is simple but limited. Real-world applications need more:

Standard Go errors:

return fmt.Errorf("user not found")
// Just a string. No classification, no metadata, no structure.

x-errors:

return xerrors.New().
    WithID("USER_NOT_FOUND").
    WithStatus(xerrors.StatusFailed).
    WithKind("validation").
    WithRealm("users").
    SetDetails("user_id", 123).
    SetDetails("attempt", 3).
    WithMessage("User {{.user_id}} not found")

🚀 Features

🏷️ Semantic Error Classification
  • IDs: Human-readable error codes (USER_NOT_FOUND, DB_TIMEOUT)
  • Status: Severity levels (Failed, Error, Fatal)
  • Meta: Categorical metadata (Kind, Realm, Operation)
📊 Rich Metadata Attachment
  • Details: Runtime context for debugging and observability
  • Type-safe getters: Generated for all common Go types (Int, String, Bool, Time, etc.)
  • Three access patterns: Get, GetOr, MustGet for safe and unsafe scenarios
🎨 Templated Messages
  • Go text/template support with dynamic data
  • Automatic error context injection
  • Lazy rendering for performance
🏗️ Reusable Error Templates
  • Define error blueprints at package level
  • Consistent error patterns across your codebase
  • Generate fresh error instances with unique UIDs
🔄 Standard Compatibility
  • Implements error interface
  • Supports errors.Is, errors.As, errors.Unwrap
  • JSON serialization ready for APIs
  • Zero allocation for common operations
Performance Optimized
  • Minimal allocations in hot paths
  • Lazy message rendering
  • Generated type-safe getters eliminate reflection
  • Pooling-friendly design

📊 Technical Specifications

Feature Specification
Minimum Go Version 1.18+ (uses generics for type safety)
License MIT - Free for commercial and personal use
Test Coverage 99%+ across all states and edge cases
Dependencies github.com/google/uuid, standard library only
API Stability Production-ready, semantic versioning
Performance Zero allocations for common operations
Serialization Full JSON support (omitempty, custom marshalers)
Concurrency Thread-safe for read operations, clone for mutation

📦 Installation

go get gitlab.sweet-mint.ru/packages/x-errors

🎯 Quick Start

Basic Usage
package main

import (
    "fmt"
    "time"

    xerrors "gitlab.sweet-mint.ru/packages/x-errors"
)

func main() {
    // Create a structured error
    err := xerrors.NewError("Database connection failed", xerrors.StatusError).
        WithID("DB_CONNECTION_FAILED").
        SetDetails("host", "db.example.com").
        SetDetails("port", 5432).
        SetDetails("timeout", 30*time.Second).
        WithMeta("operation", xerrors.NewOperation("connect")).
        WithMeta("kind", xerrors.NewKind("infrastructure"))

    // Type-safe access to details
    if host, ok := err.Details.String("host"); ok {
        fmt.Printf("Failed to connect to: %s\n", host)
    }

    // Access with defaults
    timeout := err.Details.DurationOr("timeout", 10*time.Second)

    // Check error classification
    if err.IsStatus(xerrors.StatusError) {
        // Handle serious error
        sendAlert(err)
    }

    // JSON for API responses
    jsonBytes, _ := json.MarshalIndent(err, "", "  ")
    fmt.Println(string(jsonBytes))
}
Advanced: Reusable Error Templates
package errors

import (
    xerrors "gitlab.sweet-mint.ru/packages/x-errors"
    "gitlab.sweet-mint.ru/packages/x-errors/template"
)

// Define error templates once, use everywhere
var (
    UserNotFound = template.New().
        WithID("USER_NOT_FOUND").
        WithStatus(xerrors.StatusFailed).
        WithMessage(*xerrors.NewMessage("User {{.user_id}} not found")).
        WithKind(xerrors.NewKind("validation")).
        WithRealm(xerrors.NewRealm("users")).
        WithOperation(xerrors.NewOperation("find"))

    PaymentFailed = template.New().
        WithID("PAYMENT_FAILED").
        WithStatus(xerrors.StatusError).
        WithMessage(*xerrors.NewMessage(
            "Payment of {{.amount}} {{.currency}} failed for order {{.order_id}}",
        )).
        WithKind(xerrors.NewKind("business")).
        WithRealm(xerrors.NewRealm("payments")).
        WithOperation(xerrors.NewOperation("charge"))
)

// Usage in service layer
func ProcessPayment(orderID string, amount float64, currency string) error {
    // Template + runtime data = complete error
    return PaymentFailed.
        SetDetails("order_id", orderID).
        SetDetails("amount", amount).
        SetDetails("currency", currency).
        SetDetails("timestamp", time.Now()).
        BuildWithError(paymentGatewayError)
}

🎪 Core Concepts

1. The Error Anatomy

Each xerrors.Error contains everything you need:

type Error struct {
    ID      ID              // "USER_NOT_FOUND" - semantic identifier
    UID     UID             // UUID - unique instance identifier
    Message *Message        // Templated human-readable message
    Details Details         // Runtime diagnostic data
    Status  Status          // Severity (Failed, Error, Fatal)
    Meta    Meta            // Categorical metadata
    Err     error           // Underlying wrapped error
}
2. Three-Layer Error Data
Layer Purpose Example
Semantic (ID, Status, Meta) Classification, routing, metrics ID: "VALIDATION_ERROR", Kind: "validation"
Runtime (Details) Debugging, tracing, observability user_id: 123, query_time: "2024-..."
Human (Message) User-facing descriptions "User 123 not found"
3. Generated Type-Safe Accessors

No more type assertions! Generated getters for all common types:

// For both Meta and Details
value, ok := meta.Int("retries")           // (int, bool) - safe
value := meta.IntOr("retries", 3)          // int - with default
value := meta.MustInt("retries")           // int - panic if missing

// Available for:
// - All integer types (int8, int16, int32, int64, uint, uint8...)
// - Float32, Float64
// - Bool, String, Time
// - Duration (via time.Duration)

📚 Real-World Examples

🔍 Example 1: API Validation Error

func CreateUser(w http.ResponseWriter, r *http.Request) {
    // Decode request
    var req CreateUserRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        xerr := xerrors.NewErrorWrap(err, xerrors.StatusFailed).
            WithID("INVALID_REQUEST").
            SetDetails("content_type", r.Header.Get("Content-Type"))

        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusBadRequest)
        json.NewEncoder(w).Encode(xerr) // Direct serialization
        return
    }
}

🔍 Example 2: Database "Not Found"

func FindProduct(id string) (*Product, error) {
    product, err := db.FindProduct(id)
    if errors.Is(err, sql.ErrNoRows) {
        return nil, xerrors.New().
            WithID("PRODUCT_NOT_FOUND").
            WithMessage(*xerrors.NewMessage("Product '{{.id}}' not found").
                With("id", id)).
            SetDetails("product_id", id)
    }
    return product, err
}

🔍 Example 3: Business Rule Validation

func ProcessOrder(userID int, amount float64) error {
    if amount <= 0 {
        return xerrors.NewError("Amount must be positive", xerrors.StatusFailed).
            WithID("INVALID_AMOUNT").
            SetDetails("user_id", userID).
            SetDetails("amount", amount)
    }

    balance, _ := GetBalance(userID)
    if amount > balance {
        return xerrors.NewError("Insufficient funds", xerrors.StatusFailed).
            WithID("INSUFFICIENT_FUNDS").
            SetDetails("user_id", userID).
            SetDetails("amount", amount).
            SetDetails("balance", balance)
    }

    return nil
}

🔍 Example 4: External API Call Error

func CallWeatherAPI(city string) (*Weather, error) {
    resp, err := http.Get("https://api.weather.com/" + city)
    if err != nil {
        return nil, xerrors.NewErrorWrap(err, xerrors.StatusError).
            WithID("WEATHER_API_ERROR").
            SetDetails("city", city).
            SetDetails("attempt", 1)
    }
    defer resp.Body.Close()

    if resp.StatusCode >= 400 {
        return nil, xerrors.NewError("Weather API failed", xerrors.StatusFailed).
            WithID("WEATHER_API_FAILED").
            SetDetails("city", city).
            SetDetails("status_code", resp.StatusCode)
    }

    // ... parse response
}

🔍 Example 5: Type-Safe Details Access

func HandleError(err error) {
    var xerr *xerrors.Error
    if errors.As(err, &xerr) {
        // Type-safe access to details
        if userID, ok := xerr.Details.Int("user_id"); ok {
            fmt.Printf("Error for user: %d\n", userID)
        }

        // With default value
        attempt := xerr.Details.IntOr("attempt", 1)

        // Check error classification
        if xerr.IsKind("validation") {
            logValidationError(xerr)
        }

        // Direct JSON serialization for API
        jsonBytes, _ := json.Marshal(xerr)
        fmt.Println(string(jsonBytes))
    }
}

🔍 Example 6: Simple Template Usage

// Define once
var UserNotFound = xerrors.New().
    WithID("USER_NOT_FOUND").
    WithStatus(xerrors.StatusFailed).
    WithMessage(*xerrors.NewMessage("User {{.id}} not found"))

// Use with runtime data
func GetUser(id int) (*User, error) {
    user, err := db.FindUser(id)
    if errors.Is(err, sql.ErrNoRows) {
        return nil, UserNotFound.
            Clone(). // Important: clone template
            SetDetails("user_id", id)
    }
    return user, err
}

🔍 Example 7: HTTP Middleware (Simplified)

func ErrorMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        next.ServeHTTP(w, r)

        // Check if handler set an error
        if err := GetErrorFromContext(r); err != nil {
            var xerr *xerrors.Error
            if errors.As(err, &xerr) {
                w.Header().Set("Content-Type", "application/json")
                w.WriteHeader(400)
                json.NewEncoder(w).Encode(xerr) // Direct serialization
            }
        }
    })
}

🔍 Example 8: Logging Error with Context

func LogError(err error, r *http.Request) {
    var xerr *xerrors.Error
    if errors.As(err, &xerr) {
        log.WithFields(log.Fields{
            "error_id":  xerr.ID,
            "error_uid": xerr.UID,
            "path":      r.URL.Path,
            "user_id":   xerr.Details.StringOr("user_id", "unknown"),
        }).Error(xerr.Error())
    }
}

📖 API Reference

Core Types
  • Error: Main structured error type
  • ID: Semantic error identifier (string wrapper)
  • UID: Unique occurrence identifier (UUID wrapper)
  • Status: Error severity (Unknown, Failed, Error, Fatal)
  • Message: Templated human-readable message
  • Details: Runtime diagnostic data (map with type-safe getters)
  • Meta: Categorical metadata (map with type-safe getters)

📄 License

MIT License. See LICENSE for full details.

🌟 Thank You!

  • Built with inspiration from Go's standard library errors package
  • Uses github.com/google/uuid for unique identifiers
  • Thanks to all contributors who helped shape this package

Documentation

Overview

Package xerrors provides a structured, composable error type for Go applications.

The main type in this package is Error, which encapsulates both human-readable and machine-readable error information. It is designed to make error handling, classification, propagation, and tracing consistent and structured across applications and services.

Error allows attaching metadata, structured details, unique IDs, status, and inner wrapped errors. It also provides convenience methods for building, cloning, comparing, and querying errors.

Features of xerrors.Error:

  • ID: a stable identifier for the error type (xerrors.ID).
  • UID: a unique occurrence identifier (xerrors.UID) for individual instances.
  • Message: optional human-readable message (xerrors.Message), which can be templated with dynamic data.
  • Details: arbitrary structured key/value data (xerrors.Details) for diagnostics, logging, or observability.
  • Status: categorical severity/type (xerrors.Status) such as Failed, Error, Fatal.
  • Meta: arbitrary structured metadata (xerrors.Meta), often including operational, domain, or contextual attributes such as Kind, Realm, Operation.
  • Err: an underlying wrapped error (standard Go error), excluded from JSON.

The package also provides convenient constructors, methods for cloning, error comparisons, and helpers for setting or querying metadata.

Example usage:

err := xerrors.NewError("database timeout", xerrors.StatusError)
err = err.SetMeta("operation", xerrors.NewOperation("DBQuery"))
if err.IsStatus(xerrors.StatusError) {
    log.Println(err.Error())
}

// Wrap an existing error
original := errors.New("disk full")
wrapped := xerrors.NewErrorWrap(original, xerrors.StatusFatal)

// Clone for modification
cloned := wrapped.Clone()
cloned.SetDetails("disk", "/dev/sda1")

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Details

type Details map[string]any

Details - represents structured diagnostic or context data associated with an error.

Details is typically stored inside Error.Details and is used to attach arbitrary machine-readable key/value data to an error instance.

It allows attaching contextual information such as:

  • Input parameters
  • Validation fields
  • Internal states
  • External identifiers

This makes errors more informative, searchable and suitable for structured logging, tracing systems, and API error responses.

func NewDetails

func NewDetails() Details

NewDetails - creates and returns an empty Details map.

This is a convenience constructor and behaves identically to make(Details), but provides consistency with other constructors in the xerrors package.

Example:

d := NewDetails()
d["user_id"] = 42

func (Details) Any

func (d Details) Any(key string) (any, bool)

Any - retrieves a value stored under the given key.

It returns the value and a boolean indicating whether the key exists.

Example:

d := NewDetails().With("status", "ok")
v, ok := d.Any("status")

if ok {
    fmt.Println(v) // Output: ok
}

func (Details) AnyOr

func (d Details) AnyOr(key string, def any) any

AnyOr - retrieves a value by key or returns the provided default if not present.

This is useful when working with optional fields.

Example:

d := NewDetails()
timeout := d.AnyOr("timeout", 30).(int)
fmt.Println(timeout) // Output: 30

func (Details) Bool

func (d Details) Bool(key string) (bool, bool)

Bool - retrieves a value from Details and attempts to cast it to bool.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Bool("field")
if ok {
    fmt.Println(value)
}

func (Details) BoolOr

func (d Details) BoolOr(key string, def bool) bool

BoolOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.BoolOr("timeout", false)

func (Details) Clone

func (d Details) Clone() Details

Clone - creates a deep copy of the Details map.

All keys and values are copied into a new map, but the values themselves are not deep-copied (they remain shared references if they are pointers, slices, or maps).

Example:

original := NewDetails().With("id", 1)
copy := original.Clone()
copy["id"] = 2

fmt.Println(original["id"]) // Output: 1

func (Details) Duration

func (d Details) Duration(key string) (time.Duration, bool)

Duration - retrieves a value from Details and attempts to cast it to time.Duration.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Duration("field")
if ok {
    fmt.Println(value)
}

func (Details) DurationOr

func (d Details) DurationOr(key string, def time.Duration) time.Duration

DurationOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.DurationOr("timeout", time.Duration(0))

func (Details) Float32

func (d Details) Float32(key string) (float32, bool)

Float32 - retrieves a value from Details and attempts to cast it to float32.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Float32("field")
if ok {
    fmt.Println(value)
}

func (Details) Float32Or

func (d Details) Float32Or(key string, def float32) float32

Float32Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Float32Or("timeout", 0)

func (Details) Float64

func (d Details) Float64(key string) (float64, bool)

Float64 - retrieves a value from Details and attempts to cast it to float64.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Float64("field")
if ok {
    fmt.Println(value)
}

func (Details) Float64Or

func (d Details) Float64Or(key string, def float64) float64

Float64Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Float64Or("timeout", 0)

func (Details) Int

func (d Details) Int(key string) (int, bool)

Int - retrieves a value from Details and attempts to cast it to int.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Int("field")
if ok {
    fmt.Println(value)
}

func (Details) Int8

func (d Details) Int8(key string) (int8, bool)

Int8 - retrieves a value from Details and attempts to cast it to int8.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Int8("field")
if ok {
    fmt.Println(value)
}

func (Details) Int8Or

func (d Details) Int8Or(key string, def int8) int8

Int8Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Int8Or("timeout", 0)

func (Details) Int16

func (d Details) Int16(key string) (int16, bool)

Int16 - retrieves a value from Details and attempts to cast it to int16.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Int16("field")
if ok {
    fmt.Println(value)
}

func (Details) Int16Or

func (d Details) Int16Or(key string, def int16) int16

Int16Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Int16Or("timeout", 0)

func (Details) Int32

func (d Details) Int32(key string) (int32, bool)

Int32 - retrieves a value from Details and attempts to cast it to int32.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Int32("field")
if ok {
    fmt.Println(value)
}

func (Details) Int32Or

func (d Details) Int32Or(key string, def int32) int32

Int32Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Int32Or("timeout", 0)

func (Details) Int64

func (d Details) Int64(key string) (int64, bool)

Int64 - retrieves a value from Details and attempts to cast it to int64.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Int64("field")
if ok {
    fmt.Println(value)
}

func (Details) Int64Or

func (d Details) Int64Or(key string, def int64) int64

Int64Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Int64Or("timeout", 0)

func (Details) IntOr

func (d Details) IntOr(key string, def int) int

IntOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.IntOr("timeout", 0)

func (Details) Merge

func (d Details) Merge(other Details) Details

Merge - merges another Details map into the current instance.

In case of key conflicts, values from the "other" map override existing ones.

If the receiver is nil, it is automatically initialized.

Example:

d1 := NewDetails().With("a", 1)
d2 := NewDetails().With("b", 2)

d1.Merge(d2)
fmt.Println(d1) // Output: map[a:1 b:2]

func (Details) MustAny

func (d Details) MustAny(key string) any

MustAny - retrieves a value by key and panics if the key does not exist.

This method should be used when the presence of a key is guaranteed by program logic and missing it indicates a programming error.

Example:

d := NewDetails().With("id", 123)
fmt.Println(d.MustAny("id")) // Output: 123

_ = d.MustAny("missing") // panic

func (Details) MustBool

func (d Details) MustBool(key string) bool

MustBool - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustBool("id") // panic if missing

func (Details) MustDuration

func (d Details) MustDuration(key string) time.Duration

MustDuration - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustDuration("id") // panic if missing

func (Details) MustFloat32

func (d Details) MustFloat32(key string) float32

MustFloat32 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustFloat32("id") // panic if missing

func (Details) MustFloat64

func (d Details) MustFloat64(key string) float64

MustFloat64 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustFloat64("id") // panic if missing

func (Details) MustInt

func (d Details) MustInt(key string) int

MustInt - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustInt("id") // panic if missing

func (Details) MustInt8

func (d Details) MustInt8(key string) int8

MustInt8 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustInt8("id") // panic if missing

func (Details) MustInt16

func (d Details) MustInt16(key string) int16

MustInt16 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustInt16("id") // panic if missing

func (Details) MustInt32

func (d Details) MustInt32(key string) int32

MustInt32 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustInt32("id") // panic if missing

func (Details) MustInt64

func (d Details) MustInt64(key string) int64

MustInt64 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustInt64("id") // panic if missing

func (Details) MustString

func (d Details) MustString(key string) string

MustString - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustString("id") // panic if missing

func (Details) MustTime

func (d Details) MustTime(key string) time.Time

MustTime - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustTime("id") // panic if missing

func (Details) MustUint

func (d Details) MustUint(key string) uint

MustUint - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustUint("id") // panic if missing

func (Details) MustUint8

func (d Details) MustUint8(key string) uint8

MustUint8 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustUint8("id") // panic if missing

func (Details) MustUint16

func (d Details) MustUint16(key string) uint16

MustUint16 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustUint16("id") // panic if missing

func (Details) MustUint32

func (d Details) MustUint32(key string) uint32

MustUint32 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustUint32("id") // panic if missing

func (Details) MustUint64

func (d Details) MustUint64(key string) uint64

MustUint64 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := d.MustUint64("id") // panic if missing

func (Details) String

func (d Details) String(key string) (string, bool)

String - retrieves a value from Details and attempts to cast it to string.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.String("field")
if ok {
    fmt.Println(value)
}

func (Details) StringOr

func (d Details) StringOr(key string, def string) string

StringOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.StringOr("timeout", "")

func (Details) Time

func (d Details) Time(key string) (time.Time, bool)

Time - retrieves a value from Details and attempts to cast it to time.Time.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Time("field")
if ok {
    fmt.Println(value)
}

func (Details) TimeOr

func (d Details) TimeOr(key string, def time.Time) time.Time

TimeOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.TimeOr("timeout", time.Time{})

func (Details) Uint

func (d Details) Uint(key string) (uint, bool)

Uint - retrieves a value from Details and attempts to cast it to uint.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Uint("field")
if ok {
    fmt.Println(value)
}

func (Details) Uint8

func (d Details) Uint8(key string) (uint8, bool)

Uint8 - retrieves a value from Details and attempts to cast it to uint8.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Uint8("field")
if ok {
    fmt.Println(value)
}

func (Details) Uint8Or

func (d Details) Uint8Or(key string, def uint8) uint8

Uint8Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Uint8Or("timeout", 0)

func (Details) Uint16

func (d Details) Uint16(key string) (uint16, bool)

Uint16 - retrieves a value from Details and attempts to cast it to uint16.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Uint16("field")
if ok {
    fmt.Println(value)
}

func (Details) Uint16Or

func (d Details) Uint16Or(key string, def uint16) uint16

Uint16Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Uint16Or("timeout", 0)

func (Details) Uint32

func (d Details) Uint32(key string) (uint32, bool)

Uint32 - retrieves a value from Details and attempts to cast it to uint32.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Uint32("field")
if ok {
    fmt.Println(value)
}

func (Details) Uint32Or

func (d Details) Uint32Or(key string, def uint32) uint32

Uint32Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Uint32Or("timeout", 0)

func (Details) Uint64

func (d Details) Uint64(key string) (uint64, bool)

Uint64 - retrieves a value from Details and attempts to cast it to uint64.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := d.Uint64("field")
if ok {
    fmt.Println(value)
}

func (Details) Uint64Or

func (d Details) Uint64Or(key string, def uint64) uint64

Uint64Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.Uint64Or("timeout", 0)

func (Details) UintOr

func (d Details) UintOr(key string, def uint) uint

UintOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := d.UintOr("timeout", 0)

func (Details) With

func (d Details) With(key string, value any) Details

With - adds or updates a key-value pair in the Details map and returns the same instance.

If the Details instance is nil, it is automatically initialized.

This method is intended for fluent-style chaining.

Example:

d := NewDetails().
    With("email", "test@example.com").
    With("age", 30)

type Error

type Error struct {
	// ID is the semantic identifier of the error class.
	// Example: "USER_NOT_FOUND", "DB_TIMEOUT".
	ID ID `json:"id,omitempty"`

	// UID is a unique occurrence identifier (UUID) for tracing.
	UID UID `json:"uid,omitempty"`

	// Message is an optional human-readable or templated message.
	Message *Message `json:"message,omitempty"`

	// Details is a map of arbitrary structured key/value pairs for diagnostics.
	Details Details `json:"details,omitempty"`

	// Status classifies the error by severity/type.
	Status Status `json:"status,omitempty"`

	// Meta is arbitrary metadata for classification, routing, or context.
	Meta Meta `json:"meta,omitempty"`

	// Err is an optional underlying error being wrapped.
	// This field is excluded from JSON serialization.
	Err error `json:"-"`
}

Error represents a structured error with both human-readable and machine-readable fields.

It is the primary error type of the xerrors package. Each Error instance can include:

  • ID: logical, semantic identifier of the error class.
  • UID: unique identifier of this occurrence.
  • Message: human-readable or templated message.
  • Details: structured diagnostic key/value pairs.
  • Status: error severity/type classification.
  • Meta: arbitrary additional metadata.
  • Err: optional wrapped underlying error (excluded from JSON).

func New

func New() *Error

New - creates a new Error instance with a unique UID but without setting any other fields like ID, Message, Details, Status, or Meta. Example:

e := New()
fmt.Println(e.UID)

func NewError

func NewError(text string, status Status) *Error

NewError - creates a new Error with a simple plain-text message and a specified Status. Internally, it wraps the provided message into a standard Go error. Example:

e := NewError("file not found", xerrors.StatusFailed)
fmt.Println(e.Error())

func NewErrorWrap

func NewErrorWrap(err error, status Status) *Error

NewErrorWrap - creates a new Error that wraps another existing Go error and specifies a Status. This method helps preserve the original error while adding structure and categorization. Example:

err := errors.New("connection failed")
e := NewErrorWrap(err, StatusInternal)
fmt.Println(e.Error())

func NewErrorf

func NewErrorf(status Status, format string, args ...any) *Error

NewErrorf - creates a new Error with a formatted message and a specific Status. This method is particularly useful when you want to dynamically inject values into the error message. Example:

e := NewErrorf(StatusBadRequest, "invalid input: %s", input)
fmt.Println(e.Error())

func (*Error) As

func (e *Error) As(target any) bool

As - implements type assertion for errors.As, assigning the current Error object to the target pointer if it's compatible. Example:

var target *Error
if e.As(&target) {
    fmt.Println(target.UID)
}

func (*Error) Clone

func (e *Error) Clone() *Error

Clone - creates a deep copy of the Error, including Message, Details, and Meta. The underlying wrapped error remains uncloned (shared by reference). Example:

copy := e.Clone()
fmt.Println(copy.Format())

func (*Error) Error

func (e *Error) Error() string

Error - implements the standard error interface by returning either the Message string, the wrapped error's string, or a fallback string containing the Error ID if none are available. Example:

fmt.Println(e.Error())

func (*Error) Format

func (e *Error) Format() string

Format - returns a detailed string that includes Status, ID, Meta, and the human-readable message. It's primarily used for logging and diagnostics purposes. Example:

fmt.Println(e.Format())

func (*Error) Is

func (e *Error) Is(target error) bool

Is - implements the errors.Is comparison logic, checking whether two Errors have matching IDs or Statuses. Example:

e1 := NewError("msg", xerrors.StatusFailed)
e2 := e1.Clone()
fmt.Println(e1.Is(e2)) // true

func (*Error) IsKind

func (e *Error) IsKind(k Kind) bool

IsKind - verifies if the Error contains the specified Kind within its Meta field. Returns false if Meta is nil or doesn't contain the required kind. Example:

if e.IsKind(KindValidation) { ... }

func (*Error) IsOperation

func (e *Error) IsOperation(op Operation) bool

IsOperation - determines if the Error has the given Operation stored in its Meta field. Returns false if Meta is nil or lacks the operation attribute. Example:

if e.IsOperation(OpCreate) { ... }

func (*Error) IsRealm

func (e *Error) IsRealm(r Realm) bool

IsRealm - confirms if the Error holds the given Realm inside its Meta field. Returns false if Meta is nil or does not store realm information. Example:

if e.IsRealm(RealmUser) { ... }

func (*Error) IsStatus

func (e *Error) IsStatus(s Status) bool

IsStatus - checks if the Error matches the given Status. Example:

if e.IsStatus(xerrors.StatusFailed) { ... }

func (*Error) IsZero

func (e *Error) IsZero() bool

IsZero - returns true if the Error is empty (nil) or all key fields are unset. Example:

if e.IsZero() { ... }

func (*Error) SetDetails

func (e *Error) SetDetails(key string, value any) *Error

SetDetails - inserts a single key-value pair into the Details map, initializing it if necessary. Example:

e.SetDetails("field", "invalid")

func (*Error) SetMeta

func (e *Error) SetMeta(key string, value any) *Error

SetMeta - adds a single key-value pair to the Meta map, creating the map if necessary. Example:

e.SetMeta("key", value)

func (*Error) String

func (e *Error) String() string

String - is an alias for Error(), providing a readable string representation of the error. Example:

fmt.Println(e.String())

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap - retrieves the underlying wrapped error, if one exists, allowing compatibility with errors.Unwrap. Example:

wrapped := errors.New("disk failure")
e := NewErrorWrap(wrapped, StatusInternal)
fmt.Println(errors.Unwrap(e))

func (*Error) WithDetails

func (e *Error) WithDetails(d Details) *Error

WithDetails - configures the Details map on the Error and returns the updated Error instance. Example:

e := New().WithDetails(details)

func (*Error) WithError

func (e *Error) WithError(err error) *Error

WithError - attaches an underlying error (wrapped error) to the Error instance. Example:

e := New().WithError(errors.New("io error"))

func (*Error) WithID

func (e *Error) WithID(id ID) *Error

WithID - sets the ID field on the Error and returns the modified Error instance for chaining. Example:

e := New().WithID(id)

func (*Error) WithMessage

func (e *Error) WithMessage(m Message) *Error

WithMessage - assigns the given Message to the Error and binds the entire Error instance into the message data context under the key "Error".

After calling this method, all fields of Error become available inside the message template and can be referenced via:

{{ .Error.ID }}
{{ .Error.UID }}
{{ .Error.Status }}
{{ .Error.Details }}
{{ .Error.Meta }}
{{ .Error.Err }}

This enables rich, structured message templates without duplicating or copying data into the message.

The method returns the same Error instance to allow fluent chaining.

Example:

e := New().
    WithStatus(StatusFailed).
    WithMessage(NewMessage("{{ .Error.ID }}: failed login '{{ .user }}' ").With("user", "admin"))

func (*Error) WithMessageText

func (e *Error) WithMessageText(text string) *Error

WithMessageText - sets the Message using a plain string instead of constructing a full Message object. Example:

e := New().WithMessageText("something went wrong")

func (*Error) WithMeta

func (e *Error) WithMeta(m Meta) *Error

WithMeta - updates the Meta map associated with the Error and returns the updated Error instance. Example:

e := New().WithMeta(meta)

func (*Error) WithStatus

func (e *Error) WithStatus(s Status) *Error

WithStatus - changes the Status field on the Error and returns the updated Error instance. Example:

e := New().WithStatus(xerrors.StatusFailed)

func (*Error) WithUID

func (e *Error) WithUID(uid UID) *Error

WithUID - updates the UID field on the Error and returns the updated Error instance for further operations. Example:

e := New().WithUID(uid)

type ID

type ID string

ID - represents a semantic, human-readable identifier for an error class.

ID is typically used as Error.ID and defines the logical category or identity of an error (not a unique instance).

Examples of common IDs:

  • "USER_NOT_FOUND"
  • "DB_TIMEOUT"
  • "PERMISSION_DENIED"

ID is intended for:

  • Machine classification
  • Error grouping
  • Metrics aggregation
  • Routing and filtering

It should be stable, predictable, and meaningful across versions.

func (ID) Empty

func (id ID) Empty() bool

Empty - checks whether the ID is empty.

An empty ID generally indicates a programming error or an incomplete error construction.

Example:

if id.Empty() {
    fmt.Println("missing ID")
}

func (ID) String

func (id ID) String() string

String - returns the string representation of the ID.

This is particularly useful when embedding IDs into logs, metrics labels, or error responses.

Example:

id := ID("USER_NOT_FOUND")
fmt.Println(id.String()) // Output: USER_NOT_FOUND

type Kind

type Kind string

Kind - represents a semantic classification or category of an error.

Kind is typically stored in Error.Meta to indicate the type or domain of the error (e.g., validation, system, business logic). This allows error filtering, routing, or specialized handling.

Example:

k := NewKind("validation")
fmt.Println(k) // Output: validation

func NewKind

func NewKind(v string) Kind

NewKind - creates a new Kind from a string value.

Example:

k := NewKind("authentication")
fmt.Println(k) // Output: authentication

func (Kind) Clone

func (k Kind) Clone() Kind

Clone - returns a copy of the Kind.

Example:

k2 := k.Clone()
fmt.Println(k2)

func (Kind) Empty

func (k Kind) Empty() bool

Empty - checks whether the Kind is empty.

Example:

if k.Empty() {
    fmt.Println("kind not set")
}

func (Kind) String

func (k Kind) String() string

String - returns the string representation of the Kind.

Example:

fmt.Println(k.String())

type Message

type Message struct {
	// Template - stores the raw message template.
	//
	// It may contain text/template placeholders such as:
	//
	//   "invalid field {{.field}}"
	//
	Template string

	// Data - stores named template variables.
	//
	// Map keys correspond to placeholders inside the template.
	// Values may be any type supported by text/template.
	//
	// Example:
	//
	//	Data: map[string]any{"id": 42}
	//
	Data map[string]any
}

Message - represents a lazily rendered, template-based error message.

Message is designed for structured and dynamic error descriptions. It allows you to define a message template and fill it with runtime data.

The template syntax is compatible with Go's "text/template" package.

Example template:

"User {{.user_id}} not found"

Rendering replaces placeholders using Message.Data.

Message is commonly used as Error.Message and supports:

  • Lazy rendering
  • Structured data injection
  • Cloning
  • JSON serialization

When marshaled to JSON, Message is represented as a fully rendered string.

Example usage:

msg := NewMessage("User {{.id}} not found").
    With("id", 42)

fmt.Println(msg.String()) // Output: User 42 not found

func NewMessage

func NewMessage(t string) *Message

NewMessage - creates a new Message from a template string.

This is a convenience constructor that initializes the Template field and returns a pointer for fluent chaining.

Example:

msg := NewMessage("missing field {{.name}}")

func (*Message) Clone

func (m *Message) Clone() *Message

Clone - creates a shallow copy of the Message.

The Template is copied as-is. Data is cloned using maps.Clone to avoid mutation leaks.

If the receiver is nil, Clone returns nil.

Example:

copy := msg.Clone()

func (*Message) MarshalJSON

func (m *Message) MarshalJSON() ([]byte, error)

MarshalJSON - serializes the Message as a rendered string.

This ensures that API consumers always receive a fully formatted message instead of a template with placeholders.

Example JSON:

"User 42 not found"

func (*Message) Render

func (m *Message) Render() (string, error)

Render - executes the message template using the attached data context and returns the final rendered string.

If the message was attached to an Error via Error.WithMessage, the data context contains a reference to the entire Error object under the key "Error", allowing templates to access all Error fields directly, for example:

{{ .Error.ID }}
{{ .Error.UID }}
{{ .Error.Status }}
{{ .Error.Details }}
{{ .Error.Meta }}
{{ .Error.Err }}

Behavior:

  • If Template is empty, Render returns an empty string and nil error
  • If no data is provided and the template contains no placeholders, the template is returned as-is
  • If template parsing fails, the original template is returned along with the error
  • If execution fails, the original template is returned along with the error

This method never panics and always returns a fallback-safe result.

Example:

msg := NewMessage("{{ .Error.ID }}: failed login '{{ .user }}' ").
    With("user", "admin")

s, _ := msg.Render()
fmt.Println(s) // Output: failed login: USER_NOT_FOUND

func (*Message) String

func (m *Message) String() string

String - returns the rendered message string.

Any rendering error is ignored and the raw template may be returned instead. This allows safe usage inside logging, fmt, or errors without propagation.

Example:

fmt.Println(msg.String())

func (*Message) UnmarshalJSON

func (m *Message) UnmarshalJSON(data []byte) error

UnmarshalJSON - deserializes a JSON string into Message.Template.

NOTE:

  • Only the template string is restored.
  • Data is always reset to nil.
  • This makes Message effectively immutable when loaded from JSON.

Example:

var m Message
_ = json.Unmarshal([]byte(`"Access denied"`), &m)

func (*Message) With

func (m *Message) With(k string, v any) *Message

With - attaches a variable to the template data map.

If Data was nil, it will be initialized automatically.

Returns the same instance for fluent chaining.

Example:

msg := NewMessage("missing field {{.field}}").
    With("field", "email")

type Meta

type Meta map[string]any

Meta - represents structured semantic metadata attached to an error.

Meta stores categorical and semantic attributes of an error, such as:

  • Operation — what action was being performed
  • Kind — what type of error occurred
  • Realm — in which subsystem/domain it happened

Meta is conceptually different from Details:

  • Meta is semantic and categorical
  • Details is diagnostic and contextual

Meta is typically stored in Error.Meta and is used for:

  • Error routing
  • Log classification
  • Metrics labeling
  • Alert grouping
  • Filtering and dashboards

All keys are plain strings, defined by convention.

Reserved keys:

  • "kind" → Kind
  • "realm" → Realm
  • "operation" → Operation

Example usage:

meta := NewMeta().
    WithKind(NewKind("validation")).
    WithRealm(NewRealm("user")).
    WithOperation(NewOperation("create"))

All methods support fluent chaining.

func NewMeta

func NewMeta() Meta

NewMeta - creates and returns an empty Meta map.

This is a convenience constructor and behaves the same as make(Meta), but provides consistency across the xerrors package.

Example:

meta := NewMeta()

func (Meta) Any

func (m Meta) Any(key string) (any, bool)

Any - retrieves the value stored under the specified key.

Returns the value and a boolean indicating its presence.

Example:

v, ok := meta.Any("realm")

func (Meta) AnyOr

func (m Meta) AnyOr(key string, def any) any

AnyOr - retrieves the value by key or returns the default value.

Example:

kind := meta.AnyOr("kind", NewKind("unknown")).(Kind)

func (Meta) Bool

func (m Meta) Bool(key string) (bool, bool)

Bool - retrieves a value from Meta and attempts to cast it to bool.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Bool("field")
if ok {
    fmt.Println(value)
}

func (Meta) BoolOr

func (m Meta) BoolOr(key string, def bool) bool

BoolOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.BoolOr("timeout", false)

func (Meta) Clone

func (m Meta) Clone() Meta

Clone - creates a shallow copy of the Meta map.

All keys and values are copied into a new map, but contained values themselves are not deep copied.

Example:

original := NewMeta().WithKind("db")
copy := original.Clone()

func (Meta) Duration

func (m Meta) Duration(key string) (time.Duration, bool)

Duration - retrieves a value from Meta and attempts to cast it to time.Duration.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Duration("field")
if ok {
    fmt.Println(value)
}

func (Meta) DurationOr

func (m Meta) DurationOr(key string, def time.Duration) time.Duration

DurationOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.DurationOr("timeout", time.Duration(0))

func (Meta) Float32

func (m Meta) Float32(key string) (float32, bool)

Float32 - retrieves a value from Meta and attempts to cast it to float32.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Float32("field")
if ok {
    fmt.Println(value)
}

func (Meta) Float32Or

func (m Meta) Float32Or(key string, def float32) float32

Float32Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Float32Or("timeout", 0)

func (Meta) Float64

func (m Meta) Float64(key string) (float64, bool)

Float64 - retrieves a value from Meta and attempts to cast it to float64.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Float64("field")
if ok {
    fmt.Println(value)
}

func (Meta) Float64Or

func (m Meta) Float64Or(key string, def float64) float64

Float64Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Float64Or("timeout", 0)

func (Meta) Int

func (m Meta) Int(key string) (int, bool)

Int - retrieves a value from Meta and attempts to cast it to int.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Int("field")
if ok {
    fmt.Println(value)
}

func (Meta) Int8

func (m Meta) Int8(key string) (int8, bool)

Int8 - retrieves a value from Meta and attempts to cast it to int8.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Int8("field")
if ok {
    fmt.Println(value)
}

func (Meta) Int8Or

func (m Meta) Int8Or(key string, def int8) int8

Int8Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Int8Or("timeout", 0)

func (Meta) Int16

func (m Meta) Int16(key string) (int16, bool)

Int16 - retrieves a value from Meta and attempts to cast it to int16.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Int16("field")
if ok {
    fmt.Println(value)
}

func (Meta) Int16Or

func (m Meta) Int16Or(key string, def int16) int16

Int16Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Int16Or("timeout", 0)

func (Meta) Int32

func (m Meta) Int32(key string) (int32, bool)

Int32 - retrieves a value from Meta and attempts to cast it to int32.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Int32("field")
if ok {
    fmt.Println(value)
}

func (Meta) Int32Or

func (m Meta) Int32Or(key string, def int32) int32

Int32Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Int32Or("timeout", 0)

func (Meta) Int64

func (m Meta) Int64(key string) (int64, bool)

Int64 - retrieves a value from Meta and attempts to cast it to int64.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Int64("field")
if ok {
    fmt.Println(value)
}

func (Meta) Int64Or

func (m Meta) Int64Or(key string, def int64) int64

Int64Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Int64Or("timeout", 0)

func (Meta) IntOr

func (m Meta) IntOr(key string, def int) int

IntOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.IntOr("timeout", 0)

func (Meta) Kind

func (m Meta) Kind() (Kind, bool)

Kind - retrieves the Kind field from Meta.

Returns the value and a boolean indicating existence and type validity.

Example:

k, ok := meta.Kind()

func (Meta) KindOr

func (m Meta) KindOr(def Kind) Kind

KindOr - retrieves Kind or returns a default value.

Example:

k := meta.KindOr(NewKind("unknown"))

func (Meta) Merge

func (m Meta) Merge(other Meta) Meta

Merge - merges another Meta map into the current instance.

In case of key collisions, values from "other" override existing ones.

If the receiver is nil, it is automatically initialized.

Example:

m1 := NewMeta().WithKind("validation")
m2 := NewMeta().WithRealm("user")

m1.Merge(m2)

func (Meta) MustAny

func (m Meta) MustAny(key string) any

MustAny - retrieves a value by key or panics if it does not exist.

This is intended for cases where presence is guaranteed by program logic and absence indicates a bug.

Example:

op := meta.MustAny("operation").(Operation)

func (Meta) MustBool

func (m Meta) MustBool(key string) bool

MustBool - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustBool("id") // panic if missing

func (Meta) MustDuration

func (m Meta) MustDuration(key string) time.Duration

MustDuration - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustDuration("id") // panic if missing

func (Meta) MustFloat32

func (m Meta) MustFloat32(key string) float32

MustFloat32 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustFloat32("id") // panic if missing

func (Meta) MustFloat64

func (m Meta) MustFloat64(key string) float64

MustFloat64 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustFloat64("id") // panic if missing

func (Meta) MustInt

func (m Meta) MustInt(key string) int

MustInt - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustInt("id") // panic if missing

func (Meta) MustInt8

func (m Meta) MustInt8(key string) int8

MustInt8 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustInt8("id") // panic if missing

func (Meta) MustInt16

func (m Meta) MustInt16(key string) int16

MustInt16 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustInt16("id") // panic if missing

func (Meta) MustInt32

func (m Meta) MustInt32(key string) int32

MustInt32 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustInt32("id") // panic if missing

func (Meta) MustInt64

func (m Meta) MustInt64(key string) int64

MustInt64 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustInt64("id") // panic if missing

func (Meta) MustKind

func (m Meta) MustKind() Kind

MustKind - retrieves the Kind or panics if missing or wrong type.

Example:

k := meta.MustKind()

func (Meta) MustOperation

func (m Meta) MustOperation() Operation

MustOperation - retrieves the Operation or panics if missing or wrong type.

Example:

op := meta.MustOperation()

func (Meta) MustRealm

func (m Meta) MustRealm() Realm

MustRealm - retrieves the Realm or panics if missing or wrong type.

Example:

r := meta.MustRealm()

func (Meta) MustString

func (m Meta) MustString(key string) string

MustString - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustString("id") // panic if missing

func (Meta) MustTime

func (m Meta) MustTime(key string) time.Time

MustTime - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustTime("id") // panic if missing

func (Meta) MustUint

func (m Meta) MustUint(key string) uint

MustUint - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustUint("id") // panic if missing

func (Meta) MustUint8

func (m Meta) MustUint8(key string) uint8

MustUint8 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustUint8("id") // panic if missing

func (Meta) MustUint16

func (m Meta) MustUint16(key string) uint16

MustUint16 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustUint16("id") // panic if missing

func (Meta) MustUint32

func (m Meta) MustUint32(key string) uint32

MustUint32 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustUint32("id") // panic if missing

func (Meta) MustUint64

func (m Meta) MustUint64(key string) uint64

MustUint64 - retrieves a value and panics if key is missing or invalid type.

Intended for required fields where absence indicates a programming error.

Example:

id := m.MustUint64("id") // panic if missing

func (Meta) Operation

func (m Meta) Operation() (Operation, bool)

Operation - retrieves the Operation field from Meta.

Example:

op, ok := meta.Operation()

func (Meta) OperationOr

func (m Meta) OperationOr(def Operation) Operation

OperationOr - retrieves Operation or returns a default value.

Example:

op := meta.OperationOr(NewOperation("unknown"))

func (Meta) Realm

func (m Meta) Realm() (Realm, bool)

Realm - retrieves the Realm field from Meta.

Example:

r, ok := meta.Realm()

func (Meta) RealmOr

func (m Meta) RealmOr(def Realm) Realm

RealmOr - retrieves Realm or returns a default value.

Example:

r := meta.RealmOr(NewRealm("unknown"))

func (Meta) String

func (m Meta) String(key string) (string, bool)

String - retrieves a value from Meta and attempts to cast it to string.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.String("field")
if ok {
    fmt.Println(value)
}

func (Meta) StringOr

func (m Meta) StringOr(key string, def string) string

StringOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.StringOr("timeout", "")

func (Meta) Time

func (m Meta) Time(key string) (time.Time, bool)

Time - retrieves a value from Meta and attempts to cast it to time.Time.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Time("field")
if ok {
    fmt.Println(value)
}

func (Meta) TimeOr

func (m Meta) TimeOr(key string, def time.Time) time.Time

TimeOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.TimeOr("timeout", time.Time{})

func (Meta) Uint

func (m Meta) Uint(key string) (uint, bool)

Uint - retrieves a value from Meta and attempts to cast it to uint.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Uint("field")
if ok {
    fmt.Println(value)
}

func (Meta) Uint8

func (m Meta) Uint8(key string) (uint8, bool)

Uint8 - retrieves a value from Meta and attempts to cast it to uint8.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Uint8("field")
if ok {
    fmt.Println(value)
}

func (Meta) Uint8Or

func (m Meta) Uint8Or(key string, def uint8) uint8

Uint8Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Uint8Or("timeout", 0)

func (Meta) Uint16

func (m Meta) Uint16(key string) (uint16, bool)

Uint16 - retrieves a value from Meta and attempts to cast it to uint16.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Uint16("field")
if ok {
    fmt.Println(value)
}

func (Meta) Uint16Or

func (m Meta) Uint16Or(key string, def uint16) uint16

Uint16Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Uint16Or("timeout", 0)

func (Meta) Uint32

func (m Meta) Uint32(key string) (uint32, bool)

Uint32 - retrieves a value from Meta and attempts to cast it to uint32.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Uint32("field")
if ok {
    fmt.Println(value)
}

func (Meta) Uint32Or

func (m Meta) Uint32Or(key string, def uint32) uint32

Uint32Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Uint32Or("timeout", 0)

func (Meta) Uint64

func (m Meta) Uint64(key string) (uint64, bool)

Uint64 - retrieves a value from Meta and attempts to cast it to uint64.

Returns the typed value and true on success, or zero value and false if the key does not exist or type mismatch occurs.

Example:

value, ok := m.Uint64("field")
if ok {
    fmt.Println(value)
}

func (Meta) Uint64Or

func (m Meta) Uint64Or(key string, def uint64) uint64

Uint64Or - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.Uint64Or("timeout", 0)

func (Meta) UintOr

func (m Meta) UintOr(key string, def uint) uint

UintOr - retrieves a value or returns the provided default.

If the key does not exist or type assertion fails, the provided default value is returned.

Example:

timeout := m.UintOr("timeout", 0)

func (Meta) With

func (m Meta) With(key string, value any) Meta

With - adds or updates a key-value pair in the Meta map.

If Meta is nil, it is automatically initialized.

This method is intended for fluent-style usage.

Example:

meta := NewMeta().
    With("trace_id", "abc-123").
    With("shard", 2)

func (Meta) WithKind

func (m Meta) WithKind(value Kind) Meta

WithKind - assigns the Kind semantic attribute.

Shortcut for:

m.With("kind", value)

Example:

meta := NewMeta().WithKind(NewKind("auth"))

func (Meta) WithOperation

func (m Meta) WithOperation(value Operation) Meta

WithOperation - assigns the Operation semantic attribute.

Shortcut for:

m.With("operation", value)

Example:

meta := NewMeta().WithOperation(NewOperation("update"))

func (Meta) WithRealm

func (m Meta) WithRealm(value Realm) Meta

WithRealm - assigns the Realm semantic attribute.

Shortcut for:

m.With("realm", value)

Example:

meta := NewMeta().WithRealm(NewRealm("billing"))

type Operation

type Operation string

Operation - represents the specific operation or action associated with an error.

Operation is typically stored in Error.Meta to indicate which API call, database operation, or business process triggered the error.

Example:

op := NewOperation("create")
fmt.Println(op) // Output: create

func NewOperation

func NewOperation(v string) Operation

NewOperation - creates a new Operation from a string value.

Example:

op := NewOperation("update")
fmt.Println(op) // Output: update

func (Operation) Clone

func (op Operation) Clone() Operation

Clone - returns a copy of the Operation.

Example:

op2 := op.Clone()
fmt.Println(op2)

func (Operation) Empty

func (op Operation) Empty() bool

Empty - checks whether the Operation is empty.

Example:

if op.Empty() {
    fmt.Println("operation not set")
}

func (Operation) String

func (op Operation) String() string

String - returns the string representation of the Operation.

Example:

fmt.Println(op.String())

type Realm

type Realm string

Realm - represents the domain, subsystem, or context for an error.

Realm is often used in Error.Meta to identify which system area, module, or logical domain the error is associated with (e.g., "user", "payment").

Example:

r := NewRealm("user")
fmt.Println(r) // Output: user

func NewRealm

func NewRealm(v string) Realm

NewRealm - creates a new Realm from a string value.

Example:

r := NewRealm("order")
fmt.Println(r) // Output: order

func (Realm) Clone

func (r Realm) Clone() Realm

Clone - returns a copy of the Realm.

Example:

r2 := r.Clone()
fmt.Println(r2)

func (Realm) Empty

func (r Realm) Empty() bool

Empty - checks whether the Realm is empty.

Example:

if r.Empty() {
    fmt.Println("realm not set")
}

func (Realm) String

func (r Realm) String() string

String - returns the string representation of the Realm.

Example:

fmt.Println(r.String())

type Status

type Status int

Status - represents the severity or type classification of an error.

Status is primarily used by the Error type to categorize errors by their severity level, allowing developers to handle different types of errors differently (e.g., logging, retrying, or terminating execution).

It also provides helper methods for common comparisons and supports JSON serialization/deserialization to facilitate structured logging and API responses.

const (
	// StatusUnknown - represents an undefined or unknown status.
	//
	// Typically used as a default or placeholder value when an error's
	// classification has not been explicitly set.
	StatusUnknown Status = iota

	// StatusFailed - represents a generic failure that is recoverable or expected.
	//
	// Example use case: a network request failed due to a temporary condition,
	// and retrying may succeed.
	StatusFailed

	// StatusError - represents a serious error that requires attention.
	//
	// Example use case: invalid user input, failed database query, or misconfigured resource.
	StatusError

	// StatusFatal - represents a critical failure that may halt execution.
	//
	// Example use case: unrecoverable system failure, corrupted state, or critical dependency failure.
	StatusFatal
)

func (Status) Clone

func (s Status) Clone() Status

Clone - returns a copy of the Status value.

Useful when you need to duplicate status values without modifying the original.

Example:

s1 := StatusError
s2 := s1.Clone()
fmt.Println(s2) // Output: error

func (Status) IsError

func (s Status) IsError() bool

IsError - checks whether the Status is StatusError.

Example:

if s.IsError() {
    fmt.Println("error requires attention")
}

func (Status) IsFailed

func (s Status) IsFailed() bool

IsFailed - checks whether the Status is StatusFailed.

Example:

if s.IsFailed() {
    fmt.Println("operation failed, may retry")
}

func (Status) IsFatal

func (s Status) IsFatal() bool

IsFatal - checks whether the Status is StatusFatal.

Example:

if s.IsFatal() {
    fmt.Println("critical failure, aborting")
}

func (Status) IsUnknown

func (s Status) IsUnknown() bool

IsUnknown - checks whether the Status is StatusUnknown.

Example:

if s.IsUnknown() {
    fmt.Println("status not set")
}

func (Status) MarshalJSON

func (s Status) MarshalJSON() ([]byte, error)

MarshalJSON - serializes the Status to JSON using its string representation.

This ensures that JSON logs or API responses contain human-readable status names instead of numeric values.

Example:

data, _ := json.Marshal(StatusFatal)
fmt.Println(string(data)) // Output: "fatal"

func (Status) String

func (s Status) String() string

String - returns the human-readable string representation of the Status.

This is useful for logging, displaying error status in APIs, or formatting error messages.

Example:

fmt.Println(StatusFailed.String()) // Output: "failed"

func (*Status) UnmarshalJSON

func (s *Status) UnmarshalJSON(data []byte) error

UnmarshalJSON - deserializes a JSON string into a Status value.

If the input string is unknown, it defaults to StatusUnknown and returns an error. This allows robust handling of malformed or unexpected data.

Example:

var s Status
_ = json.Unmarshal([]byte(`"error"`), &s)
fmt.Println(s) // Output: error

type UID

type UID uuid.UUID

UID - represents a unique identifier of a specific error occurrence.

This allows precise tracing of an error in logs, metrics systems, and across service boundaries.

UID is implemented as a thin wrapper around uuid.UUID.

func (UID) IsZero

func (uid UID) IsZero() bool

IsZero - checks whether the UID is empty (zero UUID).

A zero UID usually indicates that it was never initialized.

Example:

if uid.IsZero() {
    fmt.Println("UID not initialized")
}

func (UID) MarshalJSON

func (uid UID) MarshalJSON() ([]byte, error)

MarshalJSON - serializes the UID into JSON as a string.

This ensures that the UID is represented in standard UUID format rather than as raw binary data.

Example:

data, _ := json.Marshal(uid)
fmt.Println(string(data))

func (UID) String

func (uid UID) String() string

String - returns the canonical string representation of the UID.

The format is compatible with standard UUID encoding.

Example:

uid := UID(uuid.New())
fmt.Println(uid.String())

func (UID) UUID

func (uid UID) UUID() uuid.UUID

UUID - converts UID into the underlying uuid.UUID type.

This is useful when interacting with APIs or libraries that expect a standard UUID value.

Example:

raw := uid.UUID()

func (*UID) UnmarshalJSON

func (uid *UID) UnmarshalJSON(data []byte) error

UnmarshalJSON - deserializes a JSON string into a UID value.

If the JSON value is an empty string, the UID is set to uuid.Nil.

If the input string is not a valid UUID, an error is returned.

Example:

var uid UID
_ = json.Unmarshal([]byte(`"550e8400-e29b-41d4-a716-446655440000"`), &uid)

fmt.Println(uid.String())

Directories

Path Synopsis
Package template provides a reusable error template factory for building structured errors based on xerrors.
Package template provides a reusable error template factory for building structured errors based on xerrors.

Jump to

Keyboard shortcuts

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