Categorygithub.com/code19m/errx
modulepackage
0.2.3
Repository: https://github.com/code19m/errx.git
Documentation: pkg.go.dev

# README

errx: Advanced Error Handling for Go

errx is a flexible error handling package designed to provide structured, extensible, and developer-friendly error management in Go projects. It extends Go's built-in error interface with additional methods, supports gRPC integration, and includes utilities for detailed error tracing and contextual debugging.

Features

  • Extended Error Interface: Add structured details, validation fields, and trace information to errors.
  • gRPC Compatibility: Convert errors to/from gRPC status codes seamlessly.
  • Error Tracing: Automatically track the origin and flow of errors through the system.
  • Customizable Options: Use functional options to customize errors on creation or wrapping.
  • Rich Metadata: Attach contextual information and validation fields for debugging and logging.
  • Integration Utilities: Utilities for extracting or converting errors with functions like AsErrorX, GetCode, and GetType.

Installation

go get github.com/code19m/errx

Usage

0. Helper function for use in examples

func logError(err error) {
	if err == nil {
		return
	}
	e := errx.AsErrorX(err)

	logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{}))
	logger.Error("Error occurred",
		slog.String("err_code", e.Code()),
		slog.String("err_type", e.Type().String()),
		slog.String("err_message", e.Error()),
		slog.String("err_trace", e.Trace()),
		slog.Any("err_fields", e.Fields()),
		slog.Any("err_details", e.Details()),
	)
}

1. Creating Custom Errors

package main

import (
	"log/slog"
	"os"

	"github.com/code19m/errx"
)

func main() {
	err := errx.New("Resource not found",
		errx.WithCode("NOT_FOUND"),                     // Set error code
		errx.WithType(errx.T_NotFound),                 // Set error type
		errx.WithDetails(errx.M{"resource_id": "123"}), // Add additional details
		errx.WithFields(errx.M{"username": "invalid"}), // Add validation fields
	)

	logError(err)
}

Output

{
  "time": "2024-12-08T14:36:34.715364+05:00",
  "level": "ERROR",
  "msg": "Error occurred",
  "err_code": "NOT_FOUND",
  "err_type": "T_NotFound",
  "err_message": "[T_NotFound: NOT_FOUND] - Resource not found",
  "err_trace": "[main.go:28] main.main",
  "err_fields": {
    "username": "invalid"
  },
  "err_details": {
    "resource_id": "123"
  }
}

2. Wrapping Existing Errors

package main

import (
	"errors"
	"log/slog"
	"os"

	"github.com/code19m/errx"
)

func main() {
	baseErr := errors.New("database connection failed")
	err := errx.Wrap(
		baseErr,
		errx.WithDetails(errx.M{
			"host": "localhost",
			"port": "5432",
		}),
	)

	logError(err)
}

Output

{
  "time": "2024-12-08T14:42:44.488966+05:00",
  "level": "ERROR",
  "msg": "Error occurred",
  "err_code": "INTERNAL",
  "err_type": "T_Internal",
  "err_message": "[T_Internal: INTERNAL] - database connection failed",
  "err_trace": "[main.go:30] main.main",
  "err_fields": null,
  "err_details": {
    "host": "localhost",
    "port": "5432"
  }
}

3. Error trace information

package main

import (
	"log/slog"
	"os"

	"github.com/code19m/errx"
)

func main() {
	err := errx.Wrap(firstFunc())

	logError(err)
}

func firstFunc() error {
	return errx.Wrap(secondFunc())
}

func secondFunc() error {
	return errx.New("some error occurred")
}

Output

{
  "time": "2024-12-08T14:49:21.362634+05:00",
  "level": "ERROR",
  "msg": "Error occurred",
  "err_code": "INTERNAL",
  "err_type": "T_Internal",
  "err_message": "[T_Internal: INTERNAL] - some error occurred",
  "err_trace": "[main.go:28] main.main ➡️ [main.go:34] main.firstFunc ➡️ [main.go:38] main.secondFunc",
  "err_fields": null,
  "err_details": null
}

Error Types

The package defines several error types for categorizing errors:

TypeDescription
T_InternalInternal server errors
T_ValidationInput validation errors
T_NotFoundResource not found errors
T_ConflictConflicting resource errors
T_AuthenticationAuthentication-related errors
T_ForbiddenPermission-related errors

Functional Options

OptionDescription
WithCodeSets a machine-readable error code
WithTypeSets the error type
WithPrefixAdds a prefix to trace and details
WithDetailsAdds debugging details
WithFieldsSets validation-related fields

Testing

Unit tests cover the package functionality. To run tests:

go test ./...

Contributing

Contributions are welcome! Feel free to open issues or submit pull requests.

License

This package is licensed under the MIT License. See the LICENSE file for details.

License: MIT

# Functions

AsErrorX returns the error as an ErrorX instance.
FromGRPCError converts a gRPC error into a custom error (ErrorX).
GetCode returns the error code if the error implements the ErrorX interface.
GetType returns the error type if the error implements the ErrorX interface.
New creates a new ErrorX with the given message and options.
ToGRPCError converts a custom error (ErrorX) into a gRPC-compatible error.
WithCode sets the error code.
WithDetails adds additional contextual information (metadata) to the error.
WithFields sets specific validation related fields.
WithPrefix adds a prefix to the trace and all keys in the error's details, specifically designed for error propagation between microservices, particularly in gRPC communication.
WithType sets the error type.
Wrap wraps an error in an errorX instance with the given options.

# Constants

DefaultCode is the default error code used when no code is provided.
DefaultType is the default error type used when no type is provided.
Authentication errors occur when a user is not authorized to access a resource.
Conflict errors occur when a resource already exists.
Forbidden errors occur when a user is not allowed to access a resource.
Internal errors indicate unexpected issues within the application.
NotFound errors are returned when a requested resource cannot be located.
Validation errors occur when user input does not meet expected criteria.

# Interfaces

ErrorX represents a main interface of this package.

# Type aliases

M is a shorthand for a map of string key-value pairs.
OptionFunc is a function that modifies an errorX.
Type defines the different categories of errors that can be represented by an ErrorX.