errors

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Feb 24, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package errors provides structured API error types that integrate with Go's standard errors package (errors.Is, errors.As, error wrapping).

Usage:

err := errors.New(errors.CodeNotFound, "user not found")
err = err.WithStatus(404).WithDetail("user_id", "abc123")

// In handlers:
if errors.Is(err, errors.ErrNotFound) { ... }

// Automatic HTTP response:
var apiErr *errors.Error
if errors.As(err, &apiErr) {
    apiErr.StatusCode // 404
}

Index

Constants

View Source
const (
	// Client errors (4xx)
	CodeBadRequest          = "BAD_REQUEST"
	CodeUnauthorized        = "UNAUTHORIZED"
	CodeForbidden           = "FORBIDDEN"
	CodeNotFound            = "NOT_FOUND"
	CodeMethodNotAllowed    = "METHOD_NOT_ALLOWED"
	CodeConflict            = "CONFLICT"
	CodeGone                = "GONE"
	CodeValidation          = "VALIDATION_ERROR"
	CodeRateLimited         = "RATE_LIMITED"
	CodeRequestTooLarge     = "REQUEST_TOO_LARGE"
	CodeUnsupportedMedia    = "UNSUPPORTED_MEDIA_TYPE"
	CodeUnprocessable       = "UNPROCESSABLE_ENTITY"
	CodeTooManyRequests     = "TOO_MANY_REQUESTS"
	CodeInvalidCredentials  = "INVALID_CREDENTIALS"
	CodeTokenExpired        = "TOKEN_EXPIRED"
	CodeTokenInvalid        = "TOKEN_INVALID"
	CodeEmailNotVerified    = "EMAIL_NOT_VERIFIED"
	CodeInsufficientScope   = "INSUFFICIENT_SCOPE"
	CodeResourceLocked      = "RESOURCE_LOCKED"
	CodePreconditionFailed  = "PRECONDITION_FAILED"
	CodeIdempotencyConflict = "IDEMPOTENCY_CONFLICT"

	// Server errors (5xx)
	CodeInternal           = "INTERNAL_ERROR"
	CodeNotImplemented     = "NOT_IMPLEMENTED"
	CodeServiceUnavailable = "SERVICE_UNAVAILABLE"
	CodeTimeout            = "TIMEOUT"
	CodeDatabaseError      = "DATABASE_ERROR"
	CodeExternalService    = "EXTERNAL_SERVICE_ERROR"

	// Business logic errors
	CodeInsufficientFunds   = "INSUFFICIENT_FUNDS"
	CodeQuotaExceeded       = "QUOTA_EXCEEDED"
	CodeOperationNotAllowed = "OPERATION_NOT_ALLOWED"
	CodeDuplicateEntry      = "DUPLICATE_ENTRY"
)

Standard error codes. Use these as the Code field in Error for consistency across your API.

Variables

View Source
var (
	ErrBadRequest       = &Error{Code: CodeBadRequest}
	ErrUnauthorized     = &Error{Code: CodeUnauthorized}
	ErrForbidden        = &Error{Code: CodeForbidden}
	ErrNotFound         = &Error{Code: CodeNotFound}
	ErrConflict         = &Error{Code: CodeConflict}
	ErrValidation       = &Error{Code: CodeValidation}
	ErrRateLimited      = &Error{Code: CodeRateLimited}
	ErrInternal         = &Error{Code: CodeInternal}
	ErrServiceUnavail   = &Error{Code: CodeServiceUnavailable}
	ErrTokenExpired     = &Error{Code: CodeTokenExpired}
	ErrTokenInvalid     = &Error{Code: CodeTokenInvalid}
	ErrInvalidCreds     = &Error{Code: CodeInvalidCredentials}
	ErrResourceLocked   = &Error{Code: CodeResourceLocked}
	ErrDuplicateEntry   = &Error{Code: CodeDuplicateEntry}
	ErrQuotaExceeded    = &Error{Code: CodeQuotaExceeded}
	ErrTimeout          = &Error{Code: CodeTimeout}
	ErrExternalService  = &Error{Code: CodeExternalService}
	ErrInsufficientFund = &Error{Code: CodeInsufficientFunds}
)

Sentinel errors for use with errors.Is().

Usage:

if errors.Is(err, apikit.ErrNotFound) {
    // handle not found
}

These sentinels only match on Code, not on Message. This means New(CodeNotFound, "user not found") will match ErrNotFound.

Functions

func ErrorCode

func ErrorCode(err error) string

ErrorCode extracts the error code, or CodeInternal if the error is not an *Error.

func HTTPStatus

func HTTPStatus(err error) int

HTTPStatus returns the status code, or 500 if the error is not an *Error.

func RegisterCode

func RegisterCode(code string, status int)

RegisterCode registers a custom error code with its default HTTP status. It is safe for concurrent use.

func init() {
    errors.RegisterCode("SUBSCRIPTION_EXPIRED", 402)
}

Types

type Error

type Error struct {
	// StatusCode is the HTTP status code to respond with.
	StatusCode int `json:"status_code"`

	// Code is a machine-readable error code (e.g., "NOT_FOUND", "VALIDATION_ERROR").
	Code string `json:"code"`

	// Message is a human-readable error description.
	Message string `json:"message"`

	// Fields contains field-level validation errors.
	// Key is the field name, value is the error description.
	Fields map[string]string `json:"fields,omitempty"`

	// Details contains arbitrary additional error metadata.
	Details map[string]any `json:"details,omitempty"`

	// Err is the underlying wrapped error.
	Err error `json:"-"`

	// Stack holds the caller information for debugging.
	Stack string `json:"-"`
}

Error represents a structured API error. It implements the error interface and supports Go's error wrapping.

func BadRequest

func BadRequest(message string) *Error

BadRequest creates a 400 Bad Request error.

func Conflict

func Conflict(message string) *Error

Conflict creates a 409 Conflict error.

func Forbidden

func Forbidden(message string) *Error

Forbidden creates a 403 Forbidden error.

func From

func From(err error) *Error

From wraps a standard error into an API Error. If the error is already an *Error, it is returned as-is. Otherwise, it wraps the error as an internal server error.

func Fromf

func Fromf(err error, code string, format string, args ...any) *Error

Fromf wraps a standard error with a custom message.

func Internal

func Internal(message string) *Error

Internal creates a 500 Internal Server Error. The message provided should be safe to expose to clients. Wrap the original error using .Wrap(err) for logging.

func Internalf

func Internalf(err error, message string) *Error

Internalf creates a 500 error wrapping the original error. The original error is NOT exposed to clients; only the message is.

func New

func New(code string, message string) *Error

New creates a new Error with the given code and message. It captures the caller's location for debugging.

func Newf

func Newf(code string, format string, args ...any) *Error

Newf creates a new Error with a formatted message.

func NotFound

func NotFound(resource string) *Error

NotFound creates a 404 Not Found error. If resource is provided, the message will be "<resource> not found".

func RateLimited

func RateLimited(message string) *Error

RateLimited creates a 429 Too Many Requests error.

func ServiceUnavailable

func ServiceUnavailable(message string) *Error

ServiceUnavailable creates a 503 Service Unavailable error.

func Timeout

func Timeout(message string) *Error

Timeout creates a 504 Gateway Timeout error.

func Unauthorized

func Unauthorized(message string) *Error

Unauthorized creates a 401 Unauthorized error.

func Validation

func Validation(message string, fields map[string]string) *Error

Validation creates a 422 Validation error with field errors.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

func (*Error) Is

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

Is reports whether target matches this error's Code. This allows errors.Is(err, ErrNotFound) to work even when messages differ.

func (*Error) Unwrap

func (e *Error) Unwrap() error

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

func (*Error) WithDetail

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

WithDetail adds a single detail entry on a copy of the error.

func (*Error) WithDetails

func (e *Error) WithDetails(details map[string]any) *Error

WithDetails sets the details map on a copy of the error.

func (*Error) WithField

func (e *Error) WithField(field, message string) *Error

WithField adds a single field error on a copy of the error.

func (*Error) WithFields

func (e *Error) WithFields(fields map[string]string) *Error

WithFields sets multiple field errors on a copy of the error.

func (*Error) WithMessage

func (e *Error) WithMessage(msg string) *Error

WithMessage replaces the error message on a copy of the error.

func (*Error) WithStatus

func (e *Error) WithStatus(status int) *Error

WithStatus sets the HTTP status code on a copy of the error.

func (*Error) Wrap

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

Wrap wraps an underlying error on a copy of the error.

Jump to

Keyboard shortcuts

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