errors

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 8, 2026 License: MIT Imports: 9 Imported by: 12

README

errors

Build Status Go Report Card GoDoc Coverage Status

The errors package provides an enterprise-grade error handling approach.

Motivation

1. Unique Error Codes for Client Support

In many corporate applications, it’s not enough for a system to return an error - it must also return a unique, user-facing error code. This code allows end users or support engineers to reference documentation or helpdesk pages that explain what the error means, under what conditions it might occur, and how to resolve it.

These codes serve as stable references and are especially valuable in systems where frontend, backend, and support operations must all stay synchronized on error semantics.

2. Centralized Error Definitions

To make error codes reliable and consistent, they must be centrally defined and maintained in advance. Without such coordination, teams risk introducing duplicate codes, inconsistent messages, or undocumented behaviors. This package was built to support structured error registration and reuse across the entire application.

3. Logging at the Top Level & Contextual Information in Errors

There is an important idiom: log errors only once, and do it as close to the top of the call stack as possible — for instance, in an HTTP controller. Lower layers (business logic, database, etc.) may wrap and propagate errors upward, but only the outermost layer should produce the log entry.

This pattern, while clean and idiomatic, introduces a challenge: how can we include rich, contextual information at the logging point, if it was only known deep inside the application?

To solve this, we need errors that are context-aware. That is, they should carry structured attributes — like the IP address of a failing server, or the input that triggered the issue — as they move up the call stack. This package provides facilities to attach such structured context to errors and extract it later during logging or formatting.

4. Stack Traces for Root Cause Analysis

When diagnosing production issues, developers need more than just error messages — they need stack traces that show where the error originated. This is especially important when multiple wrapping or rethrowing occurs. By capturing the trace at the point of error creation, this package enables faster debugging and clearer logs.

Installation

go get github.com/axkit/errors

Error Template

Predefined errors offer reusable templates for consistent error creation. Use the Template function to declare them:

import "github.com/axkit/errors"

var (
	ErrInvalidInput = errors.Template("invalid input provided").
							Code("CRM-0901").
							StatusCode(400).
							Severity(errors.Tiny)
    
	ErrServiceUnavailable = errors.Template("service unavailable").
							Code("SRV-0253").
							StatusCode(500).
							Severity(errors.Critical)

	// Severity is `Unknown` unless set.
	ErrInvalidFilter = errors.Template("invalid filtering rule").
							Code("CRM-0042").
							StatusCode(400)

)

if request.Email == "" {
	return ErrInvalidInput.New().Msg("empty email")
}

if request.Age < 18 {
	return ErrInvalidInput.New().Set("age", request.Age).Msg("invalid age")
}

customer, err := service.CustomerByID(request.CustomerID)
if err != nil {
	return ErrServiceUnavailable.Wrap(err)
}

if customer == nil {
	return ErrInvalidInput.New().Msg("invalid customer")
}

An error remembers the template it was created from, so errors.Is(err, ErrInvalidInput) is true for every error above, even after Msg(...) or StatusCode(...) changed its attributes.

Error Structure

The Error type is the core of this package. It encapsulates metadata, stack traces, and wrapped errors.

Attributes
Attribute Description
message Error message text
severity Severity of the error (Tiny, Medium, Critical)
statusCode HTTP status code
code Application-specific error code
fields Custom key-value pairs for additional context
stack Stack frames showing the call trace

Capturing the Stack Trace

A stack trace is automatically captured at the moment an error is created or first wrapped. This allows developers to identify where the problem originated, even if the error travels up the call stack.

A stack trace is captured when one of the following methods is called:

  • errors.ErrorTemplate.New()
  • errors.ErrorTemplate.Wrap(...)
  • errors.Error.Wrap(...)
  • errors.Wrap(...)

The first frame is the line that called one of these methods.

Rewrapping an error does not overwrite an existing stack trace. The original call site remains preserved, ensuring consistent and reliable debugging information.

Each frame is written to JSON as {"func": "...", "file": "/path/to/file.go:42"}. The file:line format lets VS Code and most terminals open the file on click. In Go code the line number is also available as StackFrame.Line.

Use WithStopStackOn("fasthttp") to cut the stack at the first frame of a library you are not interested in.

Wrapping Chain

Every wrap keeps the previous error in the chain. Error() returns the messages of all levels, as usual in Go, while JSON writes each level separately:

e1 := ErrNotFound.Wrap(sql.ErrNoRows)          // "record not found", code DB-404
e2 := ErrUserLoad.Wrap(e1)                      // "failed to load user", code USR-500
e3 := errors.Wrap(e2, "handle GET /users/42")

e3.Error()
// handle GET /users/42: failed to load user: record not found: sql: no rows in result set

errors.ToJSON(e3, errors.WithAttributes(errors.AddWrappedErrors))
// {"msg":"handle GET /users/42","severity":"unknown","code":"USR-500","wrapped":[
//   {"msg":"failed to load user","severity":"unknown","code":"USR-500"},
//   {"msg":"record not found","severity":"unknown","code":"DB-404"},
//   {"msg":"sql: no rows in result set","severity":"unknown"}]}

errors.Wrap(err, msg) adds context and inherits code, status code, severity, protected flag, fields and stack of the wrapped error. Template.Wrap(err) sets the template's attributes instead.

*errors.Error implements Unwrap() and Is(), so the standard errors.Is and errors.As work with it, including errors wrapped by fmt.Errorf("...: %w", err).

Error Logging

Effective error logging is crucial for debugging and monitoring. This package encourages logging errors at the topmost layer of the application, such as an HTTP controller, while lower layers propagate errors with additional context. This ensures that logs are concise and meaningful.

var ErrInvalidObjectID = errors.Template("inalid object id").Code("CRM-0400").StatusCode(400)

// customer_repo.go
customerTable := velum.NewTable[Customer]("customers")

customer, err := customerTable.GetByPK(ctx, db, customerID)
return customer, err

// customer_service.go
customer, err := repo.CustomerByID(customerID)
if err != nil && errors.Is(err, repo.ErrNotFound) {
    return nil, ErrInvalidObjectID.Wrap(err).Set("customerId", customerID)
}

// main.go: the client gets the full JSON in development only
clientFormat := errors.ClientOutputFormat
if cfg.Env == "dev" {
	clientFormat = errors.ClientDebugOutputFormat
}

// customer_controller.go
customer, err := service.CustomerByID(customerID)
if err != nil {
	// server output (extended)
	log.Println(string(errors.ToJSON(err, errors.WithAttributes(errors.ServerOutputFormat))))

	// client output (reduced in production)
	w.Write(errors.ToJSON(err, errors.WithAttributes(clientFormat)))
}
Serialization Rules

ToJSON and Serialize write the message, severity, code and status code. Other parts are written only if requested with WithAttributes(...):

Rule Adds
AddFields fields: values set by Set(...)
AddStack stack: call frames
AddWrappedErrors wrapped: errors below the top-level one
AddProtected protected errors in wrapped
IndentJSON indented output

Predefined sets:

Set Rules
ServerOutputFormat AddFields | AddStack | AddWrappedErrors | AddProtected
ServerDebugOutputFormat ServerOutputFormat | IndentJSON
ClientDebugOutputFormat same as ServerOutputFormat
ClientOutputFormat none

WithRootLevelFields([]string{"requestId"}) moves the listed fields to the root of the JSON object. They are written even without AddFields.

Protected Errors

Mark internal errors, such as database or network errors, with Protected(true). Without AddProtected they are skipped in wrapped, so they get to the server log but not to the client:

var ErrSQL = errors.Template("pq: relation users does not exist").Code("DB-001").Protected(true)
var ErrProfile = errors.Template("cannot load profile").Code("PRF-500").StatusCode(500)

err := ErrProfile.Wrap(ErrSQL.Wrap(dbErr))

A protected error should not be the top-level one: its message is written as is. Wrap it with a public template before returning it to the client. Note that errors.Wrap(err, msg) keeps the protected flag of err.

Custom JSON Serialization

If you need to implement a custom JSON serializer, the errors.Serialize(err) method provides an object containing all public attributes of the error. This allows you to define your own serialization logic tailored to your application's requirements.

Alarm Notifications

Set an alarmer to notify on critical errors:

type CustomAlarmer struct{}

func (c *CustomAlarmer) Alarm(err error) {
    fmt.Println("Critical error:", err)
}

errors.SetAlarmer(&CustomAlarmer{})

var ErrConsistencyFailed = errors.Template("data consistency failed").Severity(errors.Critical)

// CustomAlarmer.Alarm() is called by Error.Alarm().
err := ErrConsistencyFailed.New()
err.Alarm()
return err

The alarmer is also called if ToJSON fails to marshal an error.

Severity Levels

The package classifies errors into three severity levels. A template without Severity(...) has the Unknown level.

  • Tiny: Minor issues, typically validation errors.
  • Medium: Regular errors that log stack traces.
  • Critical: Major issues requiring immediate attention.

When wrapping errors, the severity and statusCode attributes can be overridden. The client will always receive the latest severity and statusCode values from the outermost error. Any inner errors even with higher severity or different status codes will only be logged, ensuring that the most relevant information is presented to the client while maintaining detailed logs for debugging purposes.

Migration Guide

Below is a categorized list of how errors are typically created or obtained in Go code. These represent common entry points for error handling.


// 1. plain, unstructured error
return errors.New("message") 

// 2. formatted, unstructured 
return fmt.Errorf("something failed") 

// 3. wrapping + formatting
return fmt.Errorf("wrap: %w", err) 

// 4. Custom struct implementing error
return &CustomError{}

// 5. External packages returning error values
rows, err := db.Query("SELECT COUNT(1) FROM customers")
if err != nil {
	return nil, err 
}

// 6. shared "constants"
var ErrX = errors.New("...")

// 7. Sentinel errors for comparison via errors.Is(...)
// 8. Errors returned from standard library or external packages(e.g., io.EOF, pgx.ErrNoRows) 
Migration Strategy

Migrating to axkit/errors can be done incrementally, without needing to rewrite your entire codebase at once. The primary goal is to transition from unstructured error handling to a system of reusable, structured templates with support for metadata, stack traces, and observability.

Step 1: Replace the Import

Start by replacing the standard library import:

import "errors"

with:

import "github.com/axkit/errors"

This change is non-breaking: the package provides the whole API of the standard errors package — New, Is, As, Unwrap, Join, ErrUnsupported and AsType (Go 1.26). New, Unwrap, Join and ErrUnsupported are the standard ones, errors.New(...) returns a basic error without stack trace. Is, As and AsType also understand templates. This allows your application to compile and function as before.

Step 2: Identify and Replace Static Errors with Templates

Begin replacing predefined or shared errors like:

var ErrUnauthorized = errors.New("unauthorized")

with structured templates:

var ErrUnauthorized = errors.Template("unauthorized").
	Code("AAA-0401").
	StatusCode(401).
	Severity(Tiny)

I recommend placing templates at the top of each file or organizing them into a dedicated file such as errors.go, error_templates.go, etc.

Step 3: Wrap External or Lower-Level Errors

Whenever you receive an error from the standard library or a third-party package (e.g. pgx.ErrNoRows, io.EOF, sql.ErrTxDone), wrap it in your own context using a template:

customers, err := s.repo.CustomerByID(customerID)
if err == pgx.ErrNoRows {
	return ErrCustomerNotFound.Wrap(err)
}

If no reusable template exists yet, it’s acceptable to inline one during early migration:

customers, err := s.repo.CustomerByID(customerID)
if err == pgx.ErrNoRows {
	return errors.Wrap(err, "customer not found").StatusCode(400).Set("customerId", customerID)
}
Step 4: Centralize and Document Templates

As migration progresses, ensure that all templates:

  • Have a unique Code(...) identifier
  • Are grouped and reusable
  • Are linked to documentation or support systems (e.g. HelpDesk, monitoring, alerting)
  • Capture stack trace at the appropriate level via .New() or .Wrap()

This ensures a consistent and observable error-handling experience across your application.

Summary
Step Goal Complexity Backward Compatible
Step 1 Replace standard import Very Low ✅ Yes
Step 2 Use Template for shared errors Medium ✅ Yes
Step 3 Wrap external or third-party errors Medium ✅ Yes
Step 4 Centralize and document templates High (but worth it) ✅ Yes

AI Agents

The repository contains an Agent Skill with rules for idiomatic use of this package: templates, wrapping, Is/As, protected errors, logging and JSON output. Add it to a project that uses the package, so coding agents follow the same conventions.

Claude Code:

mkdir -p .claude/skills/axkit-errors
curl -sSfL https://raw.githubusercontent.com/axkit/errors/master/skills/axkit-errors/SKILL.md \
  -o .claude/skills/axkit-errors/SKILL.md

Other agents: put SKILL.md into the agent's skills directory, or reference it from AGENTS.md:

## Errors
Use github.com/axkit/errors and follow .claude/skills/axkit-errors/SKILL.md.

License

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

Documentation

Overview

Package errors provides a structured and extensible way to create, wrap, and manage errors in Go applications. It includes support for adding contextual information, managing error hierarchies, and setting attributes such as severity, HTTP status codes, and custom error codes.

The package is designed to enhance error handling by allowing developers to attach additional metadata to errors, wrap underlying errors with more context, and facilitate debugging and logging. It also supports integration with alerting systems through the Alarm method.

Key features include: - Wrapping errors with additional context. - Setting custom attributes like severity, status codes, and business codes. - Managing error stacks and hierarchies. - Sending alerts for critical errors. - Support for custom key-value pairs to enrich error information. - Integration with predefined error types for common scenarios. - Serialization errors for easy logging.

Index

Examples

Constants

View Source
const (
	ServerOutputFormat      = AddProtected | AddStack | AddFields | AddWrappedErrors
	ServerDebugOutputFormat = AddProtected | AddStack | AddFields | AddWrappedErrors | IndentJSON
	ClientDebugOutputFormat = AddProtected | AddStack | AddFields | AddWrappedErrors
	ClientOutputFormat      = 0 // no fields, no stack, no wrapped errors, only message.
)

Predefined sets of serialization rules. A typical setup writes ServerOutputFormat to the server log and sends ClientOutputFormat to the client in production or ClientDebugOutputFormat in development, so the client gets the same JSON as the log.

Variables

View Source
var (
	// CallerFramesFunc holds the function used to collect call frames
	// when an error is created or wrapped. The offset has the same meaning
	// as the skip argument of runtime.Callers called inside the collector.
	CallerFramesFunc func(offset int) []StackFrame = DefaultCallerFrames

	// CallingStackMaxLen holds maximum elements in the call frames.
	CallingStackMaxLen int = 16
)
View Source
var ErrMarshalError = Template("error marshaling failed").Severity(Critical).StatusCode(500)
View Source
var ErrUnsupported = se.ErrUnsupported

ErrUnsupported is the standard errors.ErrUnsupported, so errors.Is works the same with both packages.

Functions

func As added in v0.0.2

func As(err error, target any) bool

As finds the first error in err's chain that matches target, and if one is found, sets target to that error value and returns true.

If target is a pointer to a nil *Error, any *Error matches. If it points to a non-nil *Error, the error must match it by the rules of Is. Other targets are handled as by the standard errors.As.

func AsType added in v1.1.0

func AsType[E error](err error) (E, bool)

AsType finds the first error in err's chain that matches the type E, and if one is found, returns that error value and true. It works the same way as As and mirrors errors.AsType added in Go 1.26.

func Is added in v0.0.2

func Is(err error, target error) bool

Is reports whether any error in err's chain matches target.

An *Error matches an *ErrorTemplate if it was created from the template by New or Wrap, even if Msg, StatusCode and others changed its attributes, or if all attributes (message, severity, status code, code, protected) are equal. Two *Error values match if they are the same, were created from the same template or have equal attributes. Other errors are compared as by the standard errors.Is.

func Join added in v1.1.0

func Join(errs ...error) error

Join returns an error that wraps the given errors. Nil errors are discarded. Join returns nil if every value in errs is nil. It is the standard errors.Join.

func New

func New(msg string) error

New creates and returns a standard Go error using the built-in errors.New function.

This is implemented to maintain compatibility with existing Go error handling practices. However, the design philosophy of this package does not encourage the use of errors.New(msg) as commonly practiced in Go. Instead, it promotes the use of structured and enriched error handling mechanisms provided by this package.

func SetAlarmer added in v1.0.0

func SetAlarmer(a Alarmer)

SetAlarmer sets Alarmer implementation to be used by Error.Alarm and ToJSON.

func ToJSON added in v0.0.2

func ToJSON(err error, opts ...Option) []byte

ToJSON serializes the error to JSON format.

Example

ExampleToJSON demonstrates generating JSON output for an error.

package main

import (
	"fmt"

	"github.com/axkit/errors"
)

func main() {
	jsonErr := errors.Template("User not found").Code("E404").StatusCode(404).Severity(errors.Tiny)
	jsonOutput := errors.ToJSON(jsonErr, errors.WithAttributes(errors.AddFields))
	fmt.Println("JSON Error:", string(jsonOutput))
}
Output:
JSON Error: {"msg":"User not found","severity":"tiny","code":"E404","statusCode":404}

func Unwrap added in v0.0.2

func Unwrap(err error) error

Unwrap returns the result of calling the Unwrap method on err, if err's type contains an Unwrap method returning error. Otherwise, Unwrap returns nil. It is the standard errors.Unwrap.

Types

type Alarmer added in v0.0.2

type Alarmer interface {
	Alarm(err error)
}

Alarmer is an interface wrapping a single method Alarm.

Alarm is called by Error.Alarm and when ToJSON fails to marshal an error, if alarmer is set.

Example
package main

import (
	"fmt"

	"github.com/axkit/errors"
)

type CustomAlarmer struct{}

func (c *CustomAlarmer) Alarm(err error) {
	fmt.Println("Critical error:", err)
}

func main() {

	errors.SetAlarmer(&CustomAlarmer{})
	var ErrSystemFailure = errors.Template("system failure").Severity(errors.Critical)

	ErrSystemFailure.New().Set("path", "/var/lib").Alarm()

}
Output:
Critical error: system failure

type Error added in v1.0.0

type Error struct {
	// contains filtered or unexported fields
}

Error represents a structured error with metadata, custom fields, stack trace, and optional wrapping.

func Wrap added in v0.0.6

func Wrap(err error, message string) *Error

Wrap wraps an existing error with a new message, effectively creating a new error that includes the previous error.

If err is an *Error or *ErrorTemplate, the new error inherits its severity, status code, code, protected flag, fields and stack trace. The wrapped error stays in the chain, so Error() returns "message: <err.Error()>". The wrapped error itself is not modified.

Example

ExampleWrap demonstrates wrapping an error.

package main

import (
	"fmt"

	"github.com/axkit/errors"
)

func main() {
	innerErr := errors.Template("Database connection failed")
	outerErr := errors.Template("Service initialization failed").Wrap(innerErr)
	fmt.Println("Wrapped Error:", outerErr.Error())
}
Output:
Wrapped Error: Service initialization failed: Database connection failed

func (*Error) Alarm added in v1.0.0

func (e *Error) Alarm()

Alarm triggers an alert for the error if an alarmer is configured.

func (*Error) Code added in v1.0.0

func (e *Error) Code(code string) *Error

Code sets a custom application-specific code for the error.

func (*Error) Error added in v1.0.0

func (e *Error) Error() string

Error returns the error message, including any wrapped error messages.

Example
package main

import (
	"fmt"

	"github.com/axkit/errors"
)

func main() {

	type Input struct {
		ID        int    `json:"id"`
		FirstName string `json:"firstName"`
		LastName  string `json:"lastName"`
	}

	var ErrEmptyAttribute = errors.Template("empty attribute value").Code("CMN-0400")
	var ErrInvalidInput = errors.Template("invalid input").Code("CMN-0400")

	validateInput := func(inp *Input) error {
		if inp.ID == 0 {
			return ErrEmptyAttribute.New().Set("emptyFields", []string{"id"})
		}
		return nil
	}

	if err := validateInput(&Input{}); err != nil {
		returnErr := ErrInvalidInput.Wrap(err)
		fmt.Println(returnErr.Error())

	}
}
Output:
invalid input: empty attribute value

func (*Error) Is added in v1.1.0

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

Is reports whether the error matches target using the same rules as the package Is. It lets the standard errors.Is match templates through other wrappers, for example fmt.Errorf("...: %w", err).

func (*Error) Msg added in v1.0.0

func (e *Error) Msg(s string) *Error

Msg sets the error message and marks the error as not being a pure wrapper.

func (*Error) Protected added in v1.0.0

func (e *Error) Protected(protected bool) *Error

Protected marks the error as protected to prevent certain modifications or exposure.

func (*Error) Set added in v1.0.0

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

Set adds or updates a custom key-value pair in the error's fields.

func (*Error) Severity added in v1.0.0

func (e *Error) Severity(severity SeverityLevel) *Error

Severity sets the severity level for the error.

func (*Error) StatusCode added in v1.0.0

func (e *Error) StatusCode(statusCode int) *Error

StatusCode sets the associated HTTP status code for the error.

func (*Error) Unwrap added in v1.1.0

func (e *Error) Unwrap() error

Unwrap returns the wrapped error, so the standard errors.Is and errors.As can walk the chain.

func (*Error) Wrap added in v1.0.0

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

Wrap returns a new Error that wraps the given error while retaining the current error's metadata and fields. It also preserves the stack trace of the wrapped error if available. The new error is marked as a pure wrapper if the original error is of type ErrorTemplate or Error. If the original error is nil, it returns the current error. This method is useful for chaining errors and maintaining context. It supports wrapping both ErrorTemplate and Error types, preserving their fields and stack trace.

func (*Error) WrappedErrors added in v1.0.0

func (err *Error) WrappedErrors() []Error

WrappedErrors returns a slice of all wrapped errors, including the current one if it's not a pure wrapper.

type ErrorFormattingOptions added in v1.0.0

type ErrorFormattingOptions struct {
	// contains filtered or unexported fields
}

type ErrorSerializationRule added in v1.0.0

type ErrorSerializationRule uint8
const (

	// AddStack - add stack in the JSON.
	AddStack ErrorSerializationRule = 1 << iota

	// AddProtected - add protected errors to the "wrapped" list in the JSON.
	// Without it, wrapped errors marked with Protected(true) are skipped.
	// The top-level error is always written as is: it should not be protected,
	// wrap it with a public template before returning it to the client.
	AddProtected

	// AddFields - add custom fields set by Set() in the JSON.
	// Fields listed in WithRootLevelFields are written regardless of this rule.
	AddFields

	// AddWrappedErrors - add previous errors in the JSON.
	AddWrappedErrors

	// IndentJSON - write indented JSON.
	IndentJSON
)

type ErrorTemplate added in v1.0.0

type ErrorTemplate struct {
	// contains filtered or unexported fields
}

ErrorTemplate defines a reusable error blueprint that includes metadata and custom key-value fields. It is designed for creating structured errors with consistent attributes such as severity and HTTP status code.

Example

ExamplePredefinedErrors demonstrates using predefined errors.

package main

import (
	"fmt"

	"github.com/axkit/errors"
)

func main() {
	var ErrDatabaseDown = errors.Template("Database is unreachable").
		Code("DB-500").
		StatusCode(500).
		Severity(errors.Critical)

	if err := openDatabase("pg:5432"); err != nil {
		fmt.Println("Error:", ErrDatabaseDown.Wrap(err).Error())

	}
}

func openDatabase(connStr string) error {
	var dbErr error
	return errors.Wrap(dbErr, "unable to connect to database").Set("connectionString", connStr)
}
Output:
Error: Database is unreachable: unable to connect to database

func Template added in v1.0.0

func Template(msg string) *ErrorTemplate

Template returns a new ErrorTemplate initialized with the given message. It can be extended with additional attributes and reused to create multiple error instances.

func (*ErrorTemplate) Code added in v1.0.0

func (et *ErrorTemplate) Code(code string) *ErrorTemplate

Code sets an application-specific error code on the template.

func (*ErrorTemplate) Error added in v1.0.0

func (et *ErrorTemplate) Error() string

Error returns the error message from the template.

func (*ErrorTemplate) New added in v1.0.0

func (et *ErrorTemplate) New() *Error

New creates a new Error instance using the template's metadata and fields. A new stack trace is captured at the point of the call.

func (*ErrorTemplate) Protected added in v1.0.0

func (et *ErrorTemplate) Protected(protected bool) *ErrorTemplate

Protected marks the error as protected, indicating it should not be exposed externally.

func (*ErrorTemplate) Set added in v1.0.0

func (et *ErrorTemplate) Set(key string, value any) *ErrorTemplate

Set adds a custom key-value pair to the template's fields.

func (*ErrorTemplate) Severity added in v1.0.0

func (et *ErrorTemplate) Severity(severity SeverityLevel) *ErrorTemplate

Severity sets the severity level for the error template.

func (*ErrorTemplate) StatusCode added in v1.0.0

func (et *ErrorTemplate) StatusCode(statusCode int) *ErrorTemplate

StatusCode sets the HTTP status code associated with the error.

func (*ErrorTemplate) Wrap added in v1.0.0

func (et *ErrorTemplate) Wrap(err error) *Error

Wrap wraps an existing error with the ErrorTemplate's metadata and fields. It supports wrapping both ErrorTemplate and Error types, preserving their fields and stack trace.

type Option added in v1.0.0

type Option func(*ErrorFormattingOptions)

func WithAttributes added in v1.0.0

func WithAttributes(rule ErrorSerializationRule) Option

WithAttributes sets which parts of the error are written to the output. Without it only message, severity, code and status code are written.

func WithRootLevelFields added in v1.0.0

func WithRootLevelFields(fields []string) Option

WithRootLevelFields moves the listed fields from "fields" to the root of the JSON object. The listed fields are written even if AddFields is not set.

func WithStopStackOn added in v1.0.0

func WithStopStackOn(stopOnFuncContains string) Option

WithStopStackOn sets the function name to stop the adding stack frames. The first frame whose function name contains the string and all frames after it are not written. As instance: WithStopStackOn("fasthttp") will stop adding stack frames when the function name contains "fasthttp". It's useful to avoid adding stack frames of the libraries which are not interesting for the user.

type SerializedError added in v1.0.0

type SerializedError struct {
	Message    string            `json:"msg"`
	Severity   string            `json:"severity,omitempty"`
	Code       string            `json:"code,omitempty"`
	StatusCode int               `json:"statusCode,omitempty"`
	Fields     map[string]any    `json:"fields,omitempty"`
	Wrapped    []SerializedError `json:"wrapped,omitempty"`
	Stack      []StackFrame      `json:"stack,omitempty"`
}

SerializedError is serialization ready error.

func Serialize added in v1.0.0

func Serialize(err error, opts ...Option) *SerializedError

Serialize serializes the error to a SerializedError struct.

type SeverityLevel

type SeverityLevel int

SeverityLevel describes error severity levels.

const (
	Unknown SeverityLevel = iota
	// Tiny classifies expected, managed errors that do not require administrator attention.
	// Writing a call stack to the journal file is not recommended.
	//
	// Example: error related to validation of entered form fields.
	Tiny

	// Medium classifies a regular error. A call stack is written to the log.
	Medium

	// Critical classifies a significant error, requiring immediate attention.
	// The occurrence of the error should be communicated to the administrator
	// through all available channels. A call stack is written to the log.
	// If Alarmer is set, it will be called.
	Critical
)

func (SeverityLevel) MarshalJSON

func (sl SeverityLevel) MarshalJSON() ([]byte, error)

MarshalJSON implements json/Marshaller interface.

func (SeverityLevel) String

func (sl SeverityLevel) String() string

String returns severity level string representation.

func (*SeverityLevel) UnmarshalJSON added in v1.0.0

func (sl *SeverityLevel) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json/Unmarshaller interface.

type StackFrame added in v1.0.0

type StackFrame struct {
	Function string `json:"func"`
	File     string `json:"file"`
	Line     int    `json:"-"`
}

StackFrame describes content of a single stack frame stored with error.

File holds "path:line", so IDEs and terminals open it on click. Line holds the same line number for use in Go code. It is not written to JSON to avoid duplication and is restored from File on unmarshal.

func DefaultCallerFrames added in v0.0.2

func DefaultCallerFrames(offset int) []StackFrame

DefaultCallerFrames returns default implementation of call frames collector. The offset is the number of frames to skip, as in runtime.Callers: 0 is runtime.Callers itself, 1 is DefaultCallerFrames, 2 is its caller. The runtime.goexit frame is never included.

func (StackFrame) String added in v1.0.0

func (s StackFrame) String() string

String returns the frame as "file:line function". File collected by DefaultCallerFrames already ends with ":line", in that case the line is not appended twice.

func (*StackFrame) UnmarshalJSON added in v1.1.0

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

UnmarshalJSON implements json.Unmarshaler. Line is taken from the "line" key if present (JSON written before v1.1.0), otherwise it is parsed from the ":line" suffix of File.

Jump to

Keyboard shortcuts

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