errors

package module
v0.12.0 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 16 Imported by: 44

README

Go Errors

go-errors provides categorized Go errors with rich internal state and secure-by-default boundary output. Causes, metadata, validation values, locations, and stacks remain available programmatically, but ordinary strings, JSON, API responses, and logging do not expose them.

Install

go get github.com/goliatone/go-errors

Secure defaults

providerErr := fmt.Errorf("provider rejected client_secret=%s", secret)

err := errors.Wrap(providerErr, errors.CategoryExternal, "payment failed").
    WithCode(502).
    WithTextCode("PAYMENT_PROVIDER_FAILED").
    WithRequestID("request-123").
    WithMetadata(map[string]any{"clientSecret": secret})

fmt.Println(err)          // controlled summary; no cause or metadata
data, _ := json.Marshal(err) // PublicError JSON only
errors.LogBySeverity(logger, err) // controlled message and safe attributes

response, renderErr := err.ToPublicErrorResponse()
// response is safe and usable even when renderErr reports sanitization failure.

Default public output contains classification, a controlled message, sanitized validation field information, correlation data, and severity. It omits source text, arbitrary metadata, validation values, timestamps, locations, and stacks.

Masking is defense in depth for selected structured values. It cannot reliably find credentials embedded in arbitrary prose, so source strings and unknown metadata are omitted rather than passed through a best-effort secret scanner.

Internal state and cause chains

Error remains the internal representation:

err.Source
err.Metadata
err.ValidationErrors
err.Location
err.StackTrace

errors.Is(err, cause)
errors.As(err, &target)
errors.Unwrap(err)

Do not marshal the internal fields manually or send Source.Error() to clients or normal logs. Use public output for API boundaries and an explicitly configured diagnostic renderer for additional operational detail.

Output contexts

Renderers are immutable after construction and distinguish three contexts:

  • OutputPublic: API responses and standard JSON.
  • OutputLog: controlled log messages and allowlisted attributes.
  • OutputDiagnostic: explicitly selected, masked operational diagnostics.

Fields use FieldOmit, FieldInclude, FieldReplace, or FieldMask. Raw pass-through is rejected for messages, sources, metadata, validation data, locations, and stacks.

Controlled messages
renderer, err := errors.NewRenderer(
    errors.OutputPublic,
    errors.WithMessageResolver(func(
        context errors.OutputContext,
        input errors.MessageInput,
    ) (string, error) {
        if input.TextCode == "ACCOUNT_LOCKED" {
            return "The account is temporarily unavailable.", nil
        }
        return "The request could not be completed.", nil
    }),
)

public, renderErr := renderer.Public(errValue)

Message hooks receive immutable value snapshots, not the original error.

Allowlisted, masked metadata
renderer, err := errors.NewRenderer(
    errors.OutputLog,
    errors.WithMetadataAllowlist("provider", "attempt", "auth"),
    errors.WithMetadataFilter(func(
        context errors.OutputContext,
        key string,
        copiedValue any,
    ) (bool, error) {
        return key != "auth" || copiedValue != nil, nil
    }),
)

logRecord, renderErr := renderer.Log(errValue)

Allowlisting happens before hooks and recursive masking. Hooks operate on output copies. An allowlist is not inferred from masking rules: unlisted metadata stays omitted.

Masked diagnostics

Source and path information require dedicated replacement hooks:

renderer, err := errors.NewRenderer(
    errors.OutputDiagnostic,
    errors.WithMetadataAllowlist("provider_payload"),
    errors.WithDiagnosticValidationValues(true),
    errors.WithSourceSanitizer(func(input errors.SourceInput) (string, error) {
        return "provider request failed", nil
    }),
    errors.WithPathSanitizer(func(value string) (string, error) {
        return filepath.Base(value), nil
    }),
)

diagnostic, renderErr := renderer.FormatDiagnostic(errValue)

Without SourceSanitizer, source is omitted. Without PathSanitizer, location and stack are omitted. Diagnostic DTOs are never used by Error.MarshalJSON or standard response helpers.

Fail-closed behavior

Hook and masker failures return a usable safe result plus ErrSanitization. Rejected fields are omitted or replaced with a fixed safe value; original input is never restored.

renderer, err := errors.NewRenderer(
    errors.OutputDiagnostic,
    errors.WithSanitizationFailure(errors.SanitizationOmit, ""),
)

diagnostic, renderErr := renderer.Diagnostic(errValue)
if errors.Is(renderErr, errors.ErrSanitization) {
    // Observe the failure; diagnostic remains safe.
}

Logging

errors.LogBySeverity(logger, errValue) // fixed secure renderer

renderErr := errors.LogWithRenderer(logger, errValue, customLogRenderer)
attrs, renderErr := errors.ToSafeSlogAttributes(errValue)

Default logs include category, numeric/text codes, severity, request ID, and validation field/count information. They omit causes, stacks, and arbitrary metadata. Critical and fatal errors do not implicitly append stack traces.

Responses and validation

ErrorResponse carries *PublicError, not *Error:

response, renderErr := errValue.ToPublicErrorResponse()
data, _ := json.Marshal(response)

ToErrorResponse(includeStack, stack) remains for source compatibility, but its legacy parameters are ignored. Public responses never contain stacks.

Public validation entries contain only sanitized field and message values. The internal FieldError.Value remains available programmatically and is omitted by default. Diagnostic validation values, when explicitly enabled, are fully redacted.

Wrapping semantics

The package separates three operations:

wrapped := errors.Wrap(cause, errors.CategoryExternal, "provider request failed")
contextual := errors.AddContext(wrapped, "create invoice")
reclassified := errors.Reclassify(contextual, errors.CategoryOperation, "invoice failed")
  • Wrap creates a new outer error and honors the supplied category.
  • AddContext creates an outer error while preserving structured classification.
  • Reclassify explicitly changes category while retaining the prior chain.

All preserve errors.Is, errors.As, and errors.Unwrap traversal.

Immutable factories

Use factories when location capture must differ between consumers:

production, _ := errors.NewFactory(errors.WithLocationCapture(false))
diagnostic, _ := errors.NewFactory(errors.WithLocationCapture(true))

prodErr := production.New("operation failed", errors.CategoryOperation)
diagErr := diagnostic.Wrap(cause, errors.CategoryExternal, "provider failed")

SetLocationCapture remains an atomic compatibility setting for package constructors. Direct writes to EnableLocationCapture are deprecated and are no longer observed. Verbose and IsDevelopment are also deprecated as output controls; use renderer policies instead.

Collectors and retryable errors

Collectors and retryable errors retain their existing programmatic semantics:

collector := errors.NewCollector(
    errors.WithMaxErrors(100),
    errors.WithStrictMode(false),
)
collector.AddValidation("email", "invalid format")
collector.AddRetryable(cause, errors.CategoryExternal, "provider unavailable")

response := collector.ToErrorResponse(false)
collector.LogErrors(logger)

Responses and logs use the same safe renderers as individual errors. Merge metadata and raw validation data remain internal.

Migration from v0.11

  • Error.Error() no longer includes source, validation messages, metadata counts, location, or stack data.
  • Error.MarshalJSON() now emits the public DTO shape.
  • ErrorResponse.Error changed from *Error to *PublicError.
  • ErrorWithStack() no longer emits an unsanitized stack; use an explicit diagnostic renderer.
  • Wrap now honors its supplied category for structured errors and does not concatenate messages. Use AddContext to preserve classification.
  • Normal logging omits arbitrary metadata and validation messages.
  • Verbose, IsDevelopment, and direct writes to EnableLocationCapture no longer control output.
  • go-masker v0.2.0 is used through a dedicated immutable secure instance; the package does not mutate masker.Default.

These changes are intended for the next pre-1 minor release because they alter the default wire shape and formatting behavior.

License

MIT

Documentation

Index

Constants

View Source
const (
	TextCodeInvalidCredentials   = "INVALID_CREDENTIALS"
	TextCodeTooManyAttempts      = "TOO_MANY_ATTEMPTS"
	TextCodeSessionNotFound      = "SESSION_NOT_FOUND"
	TextCodeSessionDecodeError   = "SESSION_DECODE_ERROR"
	TextCodeClaimsMappingError   = "CLAIMS_MAPPING_ERROR"
	TextCodeDataParseError       = "DATA_PARSE_ERROR"
	TextCodeEmptyPassword        = "EMPTY_PASSWORD_NOT_ALLOWED"
	TextCodeTokenExpired         = "TOKEN_EXPIRED"
	TextCodeTokenMalformed       = "TOKEN_MALFORMED"
	TextCodeTokenAlreadyUsed     = "TOKEN_ALREADY_USED"
	TextCodeImmutableClaim       = "IMMUTABLE_CLAIM_MUTATION"
	TextCodeAccountSuspended     = "ACCOUNT_SUSPENDED"
	TextCodeAccountDisabled      = "ACCOUNT_DISABLED"
	TextCodeAccountArchived      = "ACCOUNT_ARCHIVED"
	TextCodeAccountPending       = "ACCOUNT_PENDING"
	TextCodeAccountLocked        = "ACCOUNT_LOCKED"
	TextCodeResetRateLimit       = "RESET_RATE_LIMIT"
	TextCodeResetNotAllowed      = "RESET_NOT_ALLOWED"
	TextCodeVerificationRequired = "VERIFICATION_REQUIRED"
	TextCodeVerificationExpired  = "VERIFICATION_EXPIRED"
	TextCodeInviteExpired        = "INVITE_EXPIRED"
	TextCodeInviteUsed           = "INVITE_USED"
	TextCodeFeatureDisabled      = "FEATURE_DISABLED"
)
View Source
const (
	CodeNotFound        = http.StatusNotFound
	CodeConflict        = http.StatusConflict
	CodeBadRequest      = http.StatusBadRequest
	CodeForbidden       = http.StatusForbidden
	CodeInternal        = http.StatusInternalServerError
	CodeUnauthorized    = http.StatusUnauthorized
	CodeRequestTimeout  = http.StatusRequestTimeout
	CodeTooManyRequests = http.StatusTooManyRequests
)

Variables

View Source
var (
	Verbose       = false
	IsDevelopment = false
)

Deprecated output flags retained for source compatibility. Secure output no longer reads them; configure an explicit Renderer instead.

View Source
var (
	As     = goerrors.As
	Is     = goerrors.Is
	Unwrap = goerrors.Unwrap
	Join   = goerrors.Join
)
View Source
var (
	ErrInvalidRendererOption = errors.New("invalid renderer option")
	ErrSanitization          = errors.New("output sanitization failed")
)
View Source
var EnableLocationCapture = os.Getenv("GO_ERRORS_DISABLE_LOCATION") != "true"

EnableLocationCapture is retained for source compatibility only. Deprecated: use SetLocationCapture, IsLocationCaptureEnabled, or an independently configured Factory. Direct writes are no longer observed.

Functions

func HTTPStatusToTextCode added in v0.3.0

func HTTPStatusToTextCode(code int) string

HTTPStatusToTextCode generates text codes from HTTP status codes

func HasCategory added in v0.8.0

func HasCategory(err error, category Category) bool

TODO: Should this be how IsCategory actually functions?!

func IsAuth

func IsAuth(err error) bool

func IsCategory

func IsCategory(err error, category Category) bool

func IsCommand added in v0.5.0

func IsCommand(err error) bool

func IsInternal

func IsInternal(err error) bool

func IsLocationCaptureEnabled added in v0.9.0

func IsLocationCaptureEnabled() bool

IsLocationCaptureEnabled returns the compatibility constructor setting.

func IsNotFound

func IsNotFound(err error) bool

func IsRetryableError added in v0.5.0

func IsRetryableError(err error) bool

IsRetryableError checks if an error implements the IsRetryable interface and returns true

func IsValidation

func IsValidation(err error) bool

func IsWrapped added in v0.5.1

func IsWrapped(err error) bool

IsWrapped checks if an error is already wrapped by our custom error types

func LogBySeverity added in v0.9.0

func LogBySeverity(logger *slog.Logger, err *Error)

LogBySeverity logs through the package's fixed secure log renderer.

func LogWithRenderer added in v0.12.0

func LogWithRenderer(logger *slog.Logger, err error, renderer *Renderer) error

LogWithRenderer logs using an explicitly constructed log renderer.

func RootCause added in v0.8.0

func RootCause(err error) error

func SetLocationCapture added in v0.9.0

func SetLocationCapture(enabled bool)

SetLocationCapture atomically changes the compatibility package constructors. Deprecated: prefer NewFactory with WithLocationCapture.

func ToSafeSlogAttributes added in v0.12.0

func ToSafeSlogAttributes(err error) ([]slog.Attr, error)

ToSafeSlogAttributes returns safe attributes and any sanitization failure.

func ToSlogAttributes added in v0.8.0

func ToSlogAttributes(err error) []slog.Attr

ToSlogAttributes is the compatibility form of ToSafeSlogAttributes. It discards only the observable sanitization error; rejected values remain omitted or replaced in the returned safe attributes.

Types

type BaseError added in v0.5.1

type BaseError = Error

type Category

type Category string

Category represents a high level error category

const (
	CategoryValidation       Category = "validation"
	CategoryAuth             Category = "authentication"
	CategoryAuthz            Category = "authorization"
	CategoryOperation        Category = "operation"
	CategoryNotFound         Category = "not_found"
	CategoryConflict         Category = "conflict"
	CategoryRateLimit        Category = "rate_limit"
	CategoryBadInput         Category = "bad_input"
	CategoryInternal         Category = "internal"
	CategoryExternal         Category = "external"
	CategoryMiddleware       Category = "middleware"
	CategoryRouting          Category = "routing"
	CategoryHandler          Category = "handler"
	CategoryMethodNotAllowed Category = "method_not_allowed"
	CategoryCommand          Category = "command"
)

func HTTPStatusToCategory added in v0.3.0

func HTTPStatusToCategory(code int) Category

HTTPStatusToCategory maps HTTP status codes to error categories

func RootCategory added in v0.8.0

func RootCategory(err error) Category

func (Category) Extend added in v0.5.0

func (c Category) Extend(s string) Category

func (Category) String added in v0.3.0

func (c Category) String() string

type CollectorOption added in v0.9.0

type CollectorOption func(*ErrorCollector)

CollectorOption defines functional options for ErrorCollector configuration

func WithContext added in v0.9.0

func WithContext(ctx context.Context) CollectorOption

WithContext sets the context for the collector

func WithMaxErrors added in v0.9.0

func WithMaxErrors(max int) CollectorOption

WithMaxErrors sets the maximum number of errors to collect

func WithStrictMode added in v0.9.0

func WithStrictMode(strict bool) CollectorOption

WithStrictMode enables strict mode where the collector returns false when maximum errors are reached (instead of silently dropping errors)

type DiagnosticError added in v0.12.0

type DiagnosticError struct {
	Category         Category         `json:"category,omitempty"`
	Code             int              `json:"code,omitempty"`
	TextCode         string           `json:"text_code,omitempty"`
	Message          string           `json:"message,omitempty"`
	Source           string           `json:"source,omitempty"`
	ValidationErrors ValidationErrors `json:"validation_errors,omitempty"`
	Metadata         map[string]any   `json:"metadata,omitempty"`
	RequestID        string           `json:"request_id,omitempty"`
	Timestamp        string           `json:"timestamp,omitempty"`
	Severity         Severity         `json:"severity,omitempty"`
	Location         *ErrorLocation   `json:"location,omitempty"`
	StackTrace       StackTrace       `json:"stack_trace,omitempty"`
}

DiagnosticError is an explicitly requested, policy-selected diagnostic DTO. It is never used by Error.MarshalJSON or standard API response helpers.

type DisclosurePolicy added in v0.12.0

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

DisclosurePolicy is an immutable value describing field handling.

func (DisclosurePolicy) Action added in v0.12.0

func (p DisclosurePolicy) Action(field OutputField) FieldAction

Action returns the configured action. Unknown fields are omitted.

type Error

type Error struct {
	Category         Category         `json:"category"`
	Code             int              `json:"code,omitempty"`
	TextCode         string           `json:"text_code,omitempty"`
	Message          string           `json:"message"`
	Source           error            `json:"-"`
	ValidationErrors ValidationErrors `json:"validation_errors,omitempty"`
	Metadata         map[string]any   `json:"metadata,omitempty"`
	RequestID        string           `json:"request_id,omitempty"`
	Timestamp        time.Time        `json:"timestamp"`
	StackTrace       StackTrace       `json:"stack_trace,omitempty"`
	Location         *ErrorLocation   `json:"location,omitempty"`
	Severity         Severity         `json:"severity"`
}

func AddContext added in v0.12.0

func AddContext(source error, message string) *Error

AddContext creates an outer error that preserves the nearest structured classification while retaining source as its cause.

func FromOzzoValidation added in v0.4.0

func FromOzzoValidation(err error, message string) *Error

func MapAuthErrors added in v0.3.0

func MapAuthErrors(err error) *Error

func MapHTTPErrors added in v0.3.0

func MapHTTPErrors(err error) *Error

func MapOnboardingErrors added in v0.10.0

func MapOnboardingErrors(err error) *Error

MapOnboardingErrors normalizes invite, reset, verification, and feature gate errors.

func MapToError added in v0.2.0

func MapToError(err error, mappers []ErrorMapper) *Error

MapToError converts any error to our Error type using provided mappers

func New

func New(message string, category ...Category) *Error

New creates a new Error with the specified category and message

func NewCritical added in v0.9.0

func NewCritical(message string, category Category) *Error

NewCritical creates a new Error with Critical severity

func NewDebug added in v0.9.0

func NewDebug(message string, category Category) *Error

NewDebug creates a new Error with Debug severity

func NewInfo added in v0.9.0

func NewInfo(message string, category Category) *Error

NewInfo creates a new Error with Info severity

func NewValidation

func NewValidation(message string, fieldErrors ...FieldError) *Error

func NewValidationFromGroups

func NewValidationFromGroups(message string, groups map[string][]string) *Error

func NewValidationFromMap

func NewValidationFromMap(message string, fieldMap map[string]string) *Error

func NewWarning added in v0.9.0

func NewWarning(message string, category Category) *Error

NewWarning creates a new Error with Warning severity

func NewWithLocation added in v0.9.0

func NewWithLocation(message string, category Category, location *ErrorLocation) *Error

NewWithLocation creates a new Error with explicit location setting

func Reclassify added in v0.12.0

func Reclassify(source error, category Category, message string) *Error

Reclassify creates an outer error with an explicit category while retaining source as its cause. A blank message uses the controlled category message.

func ValidateWithOzzo added in v0.4.0

func ValidateWithOzzo(validateFunc func() error, message string) *Error

func Wrap

func Wrap(source error, category Category, message string) *Error

Wrap creates a new Error that wraps an existing error

func (*Error) AllValidationErrors added in v0.8.0

func (e *Error) AllValidationErrors() ValidationErrors

func (*Error) Clone added in v0.8.0

func (e *Error) Clone() *Error

func (*Error) Error

func (e *Error) Error() string

func (*Error) ErrorWithStack

func (e *Error) ErrorWithStack() string

ErrorWithStack is retained for compatibility. It now returns the same safe summary as Error; use Renderer.FormatDiagnostic with a PathSanitizer for an explicitly selected masked diagnostic representation.

func (*Error) GetLocation added in v0.9.0

func (e *Error) GetLocation() *ErrorLocation

GetLocation returns the location where the error occurred

func (*Error) GetSeverity added in v0.9.0

func (e *Error) GetSeverity() Severity

GetSeverity returns the severity level of the error

func (*Error) HasLocation added in v0.9.0

func (e *Error) HasLocation() bool

HasLocation returns true if the error has location information

func (*Error) HasSeverity added in v0.9.0

func (e *Error) HasSeverity(s Severity) bool

HasSeverity returns true if the error has the specified severity level

func (*Error) IsAboveSeverity added in v0.9.0

func (e *Error) IsAboveSeverity(threshold Severity) bool

IsAboveSeverity returns true if the error's severity is above the threshold

func (*Error) MarshalJSON

func (e *Error) MarshalJSON() ([]byte, error)

func (*Error) ToErrorResponse added in v0.2.0

func (e *Error) ToErrorResponse(includeStack bool, stackTrace StackTrace) ErrorResponse

ToErrorResponse returns the fixed public-safe response. includeStack and stackTrace are deprecated and ignored; public responses never contain stacks.

func (*Error) ToPublicErrorResponse added in v0.12.0

func (e *Error) ToPublicErrorResponse() (ErrorResponse, error)

ToPublicErrorResponse returns a usable safe response and any sanitization error.

func (*Error) Unwrap

func (e *Error) Unwrap() error

func (*Error) ValidationMap added in v0.6.0

func (e *Error) ValidationMap() map[string]string

ValidationMap returns validation errors as a map for easy template usage

func (*Error) WithCode

func (e *Error) WithCode(code int) *Error

func (*Error) WithLocation added in v0.9.0

func (e *Error) WithLocation(loc *ErrorLocation) *Error

WithLocation sets the location where the error occurred

func (*Error) WithMetadata

func (e *Error) WithMetadata(metas ...map[string]any) *Error

func (*Error) WithRequestID

func (e *Error) WithRequestID(id string) *Error

TODO: either remove or rename to WithTraceID

func (*Error) WithSeverity added in v0.9.0

func (e *Error) WithSeverity(s Severity) *Error

WithSeverity sets the severity level of the error

func (*Error) WithStackTrace

func (e *Error) WithStackTrace() *Error

func (*Error) WithTextCode

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

type ErrorCollector added in v0.9.0

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

ErrorCollector provides thread-safe collection and aggregation of errors for batch operations and complex error handling scenarios

func NewCollector added in v0.9.0

func NewCollector(opts ...CollectorOption) *ErrorCollector

NewCollector creates a new ErrorCollector with the provided options

func (*ErrorCollector) Add added in v0.9.0

func (c *ErrorCollector) Add(err error) bool

Add adds an error to the collector in a thread-safe manner Returns true if the error was added, false if the collector is full and operating in strict mode

func (*ErrorCollector) AddFieldErrors added in v0.9.0

func (c *ErrorCollector) AddFieldErrors(errors ...FieldError)

AddFieldErrors adds multiple field errors as a single validation error

func (*ErrorCollector) AddRetryable added in v0.9.0

func (c *ErrorCollector) AddRetryable(err error, category Category, message string)

AddRetryable adds a retryable error to the collector

func (*ErrorCollector) AddValidation added in v0.9.0

func (c *ErrorCollector) AddValidation(field, message string)

AddValidation adds a validation error for a specific field

func (*ErrorCollector) CategoryStats added in v0.9.0

func (c *ErrorCollector) CategoryStats() map[Category]int

CategoryStats returns the count of errors by category

func (*ErrorCollector) Count added in v0.9.0

func (c *ErrorCollector) Count() int

Count returns the number of errors currently in the collector

func (*ErrorCollector) Errors added in v0.9.0

func (c *ErrorCollector) Errors() []*Error

Errors returns a copy of all errors in the collector

func (*ErrorCollector) FilterByCategory added in v0.9.0

func (c *ErrorCollector) FilterByCategory(cat Category) []*Error

FilterByCategory returns all errors matching the specified category

func (*ErrorCollector) FilterBySeverity added in v0.9.0

func (c *ErrorCollector) FilterBySeverity(min Severity) []*Error

FilterBySeverity returns all errors with severity at or above the specified minimum

func (*ErrorCollector) GetAllValidationErrors added in v0.9.0

func (c *ErrorCollector) GetAllValidationErrors() ValidationErrors

GetAllValidationErrors aggregates all validation errors from all collected errors This includes both direct validation errors and validation errors from wrapped errors

func (*ErrorCollector) GetRetryableErrors added in v0.9.0

func (c *ErrorCollector) GetRetryableErrors() []*Error

GetRetryableErrors returns all errors that could be considered retryable based on their severity level (errors below Critical severity)

func (*ErrorCollector) GetValidationErrors added in v0.9.0

func (c *ErrorCollector) GetValidationErrors() ValidationErrors

GetValidationErrors aggregates all validation errors from collected errors

func (*ErrorCollector) HasErrors added in v0.9.0

func (c *ErrorCollector) HasErrors() bool

HasErrors returns true if the collector contains any errors

func (*ErrorCollector) HasRetryableErrors added in v0.9.0

func (c *ErrorCollector) HasRetryableErrors() bool

HasRetryableErrors returns true if any collected errors are retryable

func (*ErrorCollector) LogErrors added in v0.9.0

func (c *ErrorCollector) LogErrors(logger *slog.Logger)

LogErrors logs all collected errors using the provided logger Each error is logged individually with its appropriate severity level

func (*ErrorCollector) Merge added in v0.9.0

func (c *ErrorCollector) Merge() *Error

Merge creates a single aggregate error from all collected errors Returns nil if no errors have been collected

func (*ErrorCollector) MostCommonCategory added in v0.9.0

func (c *ErrorCollector) MostCommonCategory() Category

MostCommonCategory returns the category with the highest error count

func (*ErrorCollector) Reset added in v0.9.0

func (c *ErrorCollector) Reset()

Reset clears all errors from the collector

func (*ErrorCollector) SeverityDistribution added in v0.9.0

func (c *ErrorCollector) SeverityDistribution() map[Severity]int

SeverityDistribution returns the count of errors by severity level

func (*ErrorCollector) ToErrorResponse added in v0.9.0

func (c *ErrorCollector) ToErrorResponse(includeStack bool) *ErrorResponse

ToErrorResponse converts the collector's state to an HTTP error response If the collector has no errors, returns nil If the collector has exactly one error, returns that error's response If the collector has multiple errors, returns a merged error response

func (*ErrorCollector) ToSlogAttributes added in v0.9.0

func (c *ErrorCollector) ToSlogAttributes() []slog.Attr

ToSlogAttributes creates slog attributes for the collector's current state Includes error count, context information, and category/severity statistics

type ErrorLocation added in v0.9.0

type ErrorLocation struct {
	File     string `json:"file"`
	Line     int    `json:"line"`
	Function string `json:"function"`
}

ErrorLocation represents the file, line, and function where an error was created

func Here added in v0.9.0

func Here() *ErrorLocation

Here captures the location where this function is called This is a convenience function for explicit location capture

func (*ErrorLocation) String added in v0.9.0

func (loc *ErrorLocation) String() string

String returns a formatted string representation of the location

type ErrorMapper added in v0.2.0

type ErrorMapper func(error) *Error

ErrorMapper is a function that can map specific error types to our Error type

func DefaultErrorMappers added in v0.3.0

func DefaultErrorMappers() []ErrorMapper

type ErrorResponse added in v0.2.0

type ErrorResponse struct {
	Error *PublicError `json:"error"`
}

ErrorResponse represents the standard structure for API error responses

type Factory added in v0.12.0

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

Factory constructs errors with immutable creation behavior.

func NewFactory added in v0.12.0

func NewFactory(options ...FactoryOption) (*Factory, error)

NewFactory creates an independent factory. Location capture defaults to true.

func (*Factory) AddContext added in v0.12.0

func (f *Factory) AddContext(source error, message string) *Error

AddContext preserves structured classification using this factory.

func (*Factory) New added in v0.12.0

func (f *Factory) New(message string, category ...Category) *Error

New constructs an Error using this factory's immutable location policy.

func (*Factory) Reclassify added in v0.12.0

func (f *Factory) Reclassify(source error, category Category, message string) *Error

Reclassify applies a new category while retaining the cause.

func (*Factory) Wrap added in v0.12.0

func (f *Factory) Wrap(source error, category Category, message string) *Error

Wrap constructs a categorized outer error using this factory.

type FactoryOption added in v0.12.0

type FactoryOption func(*factoryConfig) error

FactoryOption configures one immutable error factory.

func WithLocationCapture added in v0.12.0

func WithLocationCapture(enabled bool) FactoryOption

WithLocationCapture sets location capture for one factory.

type FieldAction added in v0.12.0

type FieldAction uint8

FieldAction controls how a selected output field is handled.

const (
	FieldOmit FieldAction = iota
	FieldInclude
	FieldReplace
	FieldMask
)

type FieldError

type FieldError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
	Value   any    `json:"value,omitempty"`
}

FieldError reprents a single validation error for a given field

func (FieldError) Error

func (e FieldError) Error() string

type FieldTransformer added in v0.12.0

type FieldTransformer func(OutputContext, OutputField, any) (any, error)

FieldTransformer replaces an already selected field before masking.

type LocationConfig added in v0.9.0

type LocationConfig struct {
	EnableLocationCapture bool
}

LocationConfig holds compatibility configuration for location capture.

type MessageInput added in v0.12.0

type MessageInput struct {
	Category Category
	Code     int
	TextCode string
	Message  string
}

MessageInput is an immutable value view for controlled message resolution.

type MessageResolver added in v0.12.0

type MessageResolver func(OutputContext, MessageInput) (string, error)

MessageResolver returns a controlled message for one output context.

type MetadataFilter added in v0.12.0

type MetadataFilter func(OutputContext, string, any) (bool, error)

MetadataFilter selects an individual metadata key before copying and masking.

type OutputContext added in v0.12.0

type OutputContext uint8

OutputContext identifies a boundary with a distinct disclosure policy.

const (
	OutputPublic OutputContext = iota
	OutputLog
	OutputDiagnostic
)

type OutputField added in v0.12.0

type OutputField uint8

OutputField identifies a rich-error field that can be governed by policy.

const (
	FieldCategory OutputField = iota
	FieldCode
	FieldTextCode
	FieldMessage
	FieldSource
	FieldValidation
	FieldMetadata
	FieldRequestID
	FieldTimestamp
	FieldSeverity
	FieldLocation
	FieldStack
)

type OutputIssue added in v0.12.0

type OutputIssue struct {
	Field OutputField
	Stage string
	Err   error
}

OutputIssue identifies one field that was safely omitted or replaced.

type OutputMasker added in v0.12.0

type OutputMasker interface {
	Mask(any) (any, error)
	String(tag, value string) (string, error)
}

OutputMasker is the minimal masking contract used by Renderer. Implementations must return copied values and must be safe for concurrent use after construction.

type PathSanitizer added in v0.12.0

type PathSanitizer func(string) (string, error)

PathSanitizer replaces or trims a file path or function name.

type PublicError added in v0.12.0

type PublicError struct {
	Category         Category                `json:"category,omitempty"`
	Code             int                     `json:"code,omitempty"`
	TextCode         string                  `json:"text_code,omitempty"`
	Message          string                  `json:"message,omitempty"`
	ValidationErrors []PublicValidationError `json:"validation_errors,omitempty"`
	RequestID        string                  `json:"request_id,omitempty"`
	Severity         Severity                `json:"severity,omitempty"`
}

PublicError contains only fields that have dedicated public-safe semantics.

type PublicValidationError added in v0.12.0

type PublicValidationError struct {
	Field   string `json:"field"`
	Message string `json:"message"`
}

PublicValidationError is the only validation shape used on public boundaries. It deliberately has no Value field.

type Renderer added in v0.12.0

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

Renderer is immutable after construction and safe for concurrent rendering when its supplied hooks and masker are safe for concurrent use.

func NewRenderer added in v0.12.0

func NewRenderer(context OutputContext, options ...RendererOption) (*Renderer, error)

NewRenderer constructs an immutable renderer with secure defaults for context.

func (*Renderer) Context added in v0.12.0

func (r *Renderer) Context() OutputContext

Context returns the renderer's fixed output context.

func (*Renderer) Diagnostic added in v0.12.0

func (r *Renderer) Diagnostic(input error) (*DiagnosticError, error)

Diagnostic renders an explicitly selected diagnostic DTO.

func (*Renderer) FieldAction added in v0.12.0

func (r *Renderer) FieldAction(field OutputField) FieldAction

FieldAction returns the renderer's fixed action for field.

func (*Renderer) FormatDiagnostic added in v0.12.0

func (r *Renderer) FormatDiagnostic(input error) (string, error)

FormatDiagnostic returns an explicitly requested JSON diagnostic string. Only fields selected and sanitized by this diagnostic renderer are present.

func (*Renderer) Log added in v0.12.0

func (r *Renderer) Log(input error) (SafeLogRecord, error)

Log renders the safe message and allowlisted attributes for a log context.

func (*Renderer) MarshalDiagnostic added in v0.12.0

func (r *Renderer) MarshalDiagnostic(input error) ([]byte, error)

MarshalDiagnostic renders and JSON-encodes an explicitly diagnostic output.

func (*Renderer) Public added in v0.12.0

func (r *Renderer) Public(input error) (*PublicError, error)

Public renders a public DTO and a separately observable sanitization error.

type RendererOption added in v0.12.0

type RendererOption func(*rendererConfig) error

RendererOption configures one renderer during construction.

func WithDiagnosticValidationValues added in v0.12.0

func WithDiagnosticValidationValues(enabled bool) RendererOption

WithDiagnosticValidationValues enables fixed-redacted validation values.

func WithFieldTransformer added in v0.12.0

func WithFieldTransformer(transformer FieldTransformer) RendererOption

WithFieldTransformer configures narrowly scoped selected-field replacement.

func WithMessageResolver added in v0.12.0

func WithMessageResolver(resolver MessageResolver) RendererOption

WithMessageResolver configures controlled message replacement.

func WithMetadataAllowlist added in v0.12.0

func WithMetadataAllowlist(keys ...string) RendererOption

WithMetadataAllowlist selects metadata keys before hooks and masking.

func WithMetadataFilter added in v0.12.0

func WithMetadataFilter(filter MetadataFilter) RendererOption

WithMetadataFilter configures filtering after allowlisting and copying.

func WithPathSanitizer added in v0.12.0

func WithPathSanitizer(sanitizer PathSanitizer) RendererOption

WithPathSanitizer enables replacement of diagnostic paths and functions.

func WithRendererFieldAction added in v0.12.0

func WithRendererFieldAction(field OutputField, action FieldAction) RendererOption

WithRendererFieldAction overrides one field action at construction time.

func WithRendererMasker added in v0.12.0

func WithRendererMasker(outputMasker OutputMasker) RendererOption

WithRendererMasker replaces the renderer's dedicated masker.

func WithSanitizationFailure added in v0.12.0

func WithSanitizationFailure(action SanitizationFailureAction, replacement string) RendererOption

WithSanitizationFailure configures omission or a fixed safe replacement.

func WithSourceSanitizer added in v0.12.0

func WithSourceSanitizer(sanitizer SourceSanitizer) RendererOption

WithSourceSanitizer allows source representation only through replacement.

type RetryableError added in v0.5.0

type RetryableError struct {
	*BaseError
	// contains filtered or unexported fields
}

RetryableError extends Error with retry functionality

func NewNonRetryable added in v0.5.0

func NewNonRetryable(message string, category Category) *RetryableError

NewNonRetryable creates a non-retryable error (useful for validation, auth, etc.)

func NewRetryable added in v0.5.0

func NewRetryable(message string, category Category) *RetryableError

func NewRetryableExternal added in v0.5.0

func NewRetryableExternal(message string) *RetryableError

NewRetryableExternal creates a retryable error for an external service

func NewRetryableOperation added in v0.5.0

func NewRetryableOperation(message string, delay ...time.Duration) *RetryableError

NewRetryableOperation creates a retryable error for operation failures with a short delay of 500 millis by default

func WrapRetryable added in v0.5.0

func WrapRetryable(source error, category Category, message string) *RetryableError

func (*RetryableError) Error added in v0.5.1

func (r *RetryableError) Error() string

func (*RetryableError) IsRetryable added in v0.5.0

func (r *RetryableError) IsRetryable() bool

IsRetryable returns whether this error should trigger a retry Critical and Fatal errors are never retryable regardless of the retryable flag

func (*RetryableError) RetryDealy added in v0.5.0

func (r *RetryableError) RetryDealy(attempt int) time.Duration

RetryDealy is kept for backward compatibility. Use RetryDelay.

func (*RetryableError) RetryDelay added in v0.11.0

func (r *RetryableError) RetryDelay(attempt int) time.Duration

RetryDelay calculates the delay before the next retry attempt Uses exponential backoff: baseDelay * (2^(attempt-1))

func (*RetryableError) Unwrap added in v0.11.0

func (r *RetryableError) Unwrap() error

func (*RetryableError) WithCode added in v0.5.0

func (r *RetryableError) WithCode(code int) *RetryableError

func (*RetryableError) WithLocation added in v0.9.0

func (r *RetryableError) WithLocation(loc *ErrorLocation) *RetryableError

WithLocation sets the location where the error occurred

func (*RetryableError) WithMetadata added in v0.5.0

func (r *RetryableError) WithMetadata(metas ...map[string]any) *RetryableError

func (*RetryableError) WithRetryDelay added in v0.5.0

func (r *RetryableError) WithRetryDelay(delay time.Duration) *RetryableError

WithRetryDelay sets the base delay for retry attempts

func (*RetryableError) WithRetryable added in v0.5.0

func (r *RetryableError) WithRetryable(retryable bool) *RetryableError

WithRetryable sets whether this error should be retryable

func (*RetryableError) WithSeverity added in v0.9.0

func (r *RetryableError) WithSeverity(s Severity) *RetryableError

WithSeverity sets the severity level of the retryable error

func (*RetryableError) WithStackTrace added in v0.5.0

func (r *RetryableError) WithStackTrace() *RetryableError

func (*RetryableError) WithTextCode added in v0.5.0

func (r *RetryableError) WithTextCode(code string) *RetryableError

type SafeLogRecord added in v0.12.0

type SafeLogRecord struct {
	Message    string
	Severity   Severity
	Attributes []slog.Attr
}

SafeLogRecord is a renderer-produced logging representation.

type SanitizationError added in v0.12.0

type SanitizationError struct {
	Issues []OutputIssue
}

SanitizationError reports rejected output while the returned representation remains safe and usable.

func (*SanitizationError) Error added in v0.12.0

func (e *SanitizationError) Error() string

func (*SanitizationError) Unwrap added in v0.12.0

func (e *SanitizationError) Unwrap() []error

type SanitizationFailureAction added in v0.12.0

type SanitizationFailureAction uint8

SanitizationFailureAction is deliberately limited to fail-closed behavior.

const (
	SanitizationOmit SanitizationFailureAction = iota
	SanitizationReplace
)

type Severity added in v0.9.0

type Severity int

Severity represents the severity level of an error

const (
	SeverityDebug Severity = iota
	SeverityInfo
	SeverityWarning
	SeverityError
	SeverityCritical
	SeverityFatal
)

func (Severity) MarshalJSON added in v0.9.0

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

MarshalJSON implements JSON marshaling for Severity

func (Severity) String added in v0.9.0

func (s Severity) String() string

String returns the string representation of the severity level

func (*Severity) UnmarshalJSON added in v0.9.0

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

UnmarshalJSON implements JSON unmarshaling for Severity

type SourceInput added in v0.12.0

type SourceInput struct {
	Type string
	Text string
}

SourceInput is an immutable snapshot of an arbitrary source error.

type SourceSanitizer added in v0.12.0

type SourceSanitizer func(SourceInput) (string, error)

SourceSanitizer replaces an arbitrary source snapshot with safe text.

type StackFrame

type StackFrame struct {
	Function string `json:"function"`
	File     string `json:"file"`
	Line     int    `json:"line"`
}

StackFrame is a single frame in the stack trace

type StackTrace

type StackTrace []StackFrame

StackTrace is a collection of stack frames

func CaptureStackTrace

func CaptureStackTrace(skip int) StackTrace

func (StackTrace) String

func (s StackTrace) String() string

type ValidationErrors

type ValidationErrors []FieldError

ValidationErrors is a collection of field level validation errors

func GetValidationErrors

func GetValidationErrors(err error) (ValidationErrors, bool)

func (ValidationErrors) Error

func (e ValidationErrors) Error() string

Jump to

Keyboard shortcuts

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