Documentation
¶
Overview ¶
Package errors provides unified error handling for Go services. It implements structured error types with error codes, HTTP status mapping, and retryable detection following RFC 9457 and Google AIP-193.
Package errors provides unified error handling for Go services. It implements structured error types with error codes, HTTP status mapping, and retryable detection following RFC 9457 and Google AIP-193.
Index ¶
- func GetTypeBaseURI() string
- func IsAppError(err error) bool
- func IsRetryableCode(code ErrorCode) bool
- func SetTypeBaseURI(uri string)
- type AppError
- func AlreadyExists(resource string) *AppError
- func AsAppError(err error) (*AppError, bool)
- func Canceled(operation string) *AppError
- func Conflict(reason string) *AppError
- func ConnectionFailed(service string) *AppError
- func DatabaseError(cause error) *AppError
- func ExternalServiceError(service string, cause error) *AppError
- func Forbidden(reason string) *AppError
- func FormatResourceError[T any](resource string, id T) *AppError
- func Internal(cause error) *AppError
- func InvalidFormat(field, expectedFormat string) *AppError
- func InvalidInput(field, reason string) *AppError
- func InvalidToken() *AppError
- func MissingField(field string) *AppError
- func New(code ErrorCode, message string, httpStatus int) *AppError
- func NotFound(resource, id string) *AppError
- func RateLimited() *AppError
- func ServiceUnavailable(service string) *AppError
- func Timeout(operation string) *AppError
- func TokenExpired() *AppError
- func Unauthorized(reason string) *AppError
- func Validation(message string) *AppError
- func Wrap(err error) *AppError
- type ErrorCode
- type ProblemDetail
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetTypeBaseURI ¶
func GetTypeBaseURI() string
GetTypeBaseURI returns the current base URI, materializing the default on first call.
func IsRetryableCode ¶
IsRetryableCode returns true if the error code indicates a retryable error.
func SetTypeBaseURI ¶
func SetTypeBaseURI(uri string)
SetTypeBaseURI sets the base URI used when constructing ProblemDetail.Type. The uri is normalised to always end with "/".
Types ¶
type AppError ¶
type AppError struct {
// Code is a machine-readable error code.
Code ErrorCode `json:"code"`
// Message is a human-readable error message.
Message string `json:"message"`
// Retryable indicates if the operation can be retried.
Retryable bool `json:"retryable"`
// HTTPStatus is the recommended HTTP status code for this error.
HTTPStatus int `json:"-"`
// Details carries RFC 9457 problem-detail extension members. These are, by definition,
// arbitrary JSON and cannot be given a closed type without losing that openness,
// so map[string]any is a deliberate,
// documented opaque-value exception to the no-any rule (parity with rskit's HashMap<String, Value>).
// Values should be JSON-encodable.
Details map[string]any `json:"details,omitempty"`
// Cause is the underlying error that caused this error.
Cause error `json:"-"`
}
AppError is the unified application error type.
func AlreadyExists ¶
AlreadyExists creates a new AppError for a resource that already exists.
func AsAppError ¶
AsAppError converts an error to an AppError if possible.
func Conflict ¶
Conflict creates a new AppError for a conflict with the current state of the resource.
func ConnectionFailed ¶
ConnectionFailed creates a new AppError for a failed connection to a service.
func DatabaseError ¶
DatabaseError creates a new AppError for a database error.
func ExternalServiceError ¶
ExternalServiceError creates a new AppError for an error from an external service.
func FormatResourceError ¶
FormatResourceError creates a not-found error with a formatted identifier of any type. The identifier is rendered with the default format verb.
func InvalidFormat ¶
InvalidFormat creates a new AppError for an invalid field format.
func InvalidInput ¶
InvalidInput creates a new AppError for invalid input.
func InvalidToken ¶
func InvalidToken() *AppError
InvalidToken creates a new AppError for an invalid authentication token.
func MissingField ¶
MissingField creates a new AppError for a missing required field.
func NotFound ¶
NotFound creates a new AppError for a resource that was not found.
Example ¶
package main
import (
"fmt"
"github.com/kbukum/gokit/errors"
)
func main() {
err := errors.NotFound("user", "42")
fmt.Println(err)
}
Output: NOT_FOUND: The requested user was not found.
func RateLimited ¶
func RateLimited() *AppError
RateLimited creates a new AppError for too many requests.
func ServiceUnavailable ¶
ServiceUnavailable creates a new AppError for a service that is temporarily unavailable.
func TokenExpired ¶
func TokenExpired() *AppError
TokenExpired creates a new AppError for an expired authentication token.
func Unauthorized ¶
Unauthorized creates a new AppError for unauthorized access.
func Validation ¶
Validation creates a new AppError for validation errors.
func Wrap ¶
Wrap converts a standard error to an AppError. If the error is already an AppError it is returned as-is; otherwise it is wrapped as Internal. Returns nil when err is nil.
func (*AppError) ToProblemDetail ¶
func (e *AppError) ToProblemDetail() ProblemDetail
ToProblemDetail converts an AppError to a ProblemDetail following RFC 9457. Instance is left empty and should be populated by the HTTP middleware.
func (*AppError) Unwrap ¶
Unwrap returns the underlying cause of the error.
Example ¶
package main
import (
stderrors "errors"
"fmt"
"github.com/kbukum/gokit/errors"
)
func main() {
cause := stderrors.New("connection refused")
err := errors.ConnectionFailed("redis").WithCause(cause)
if stderrors.Is(err, cause) {
fmt.Println("cause preserved")
}
}
Output: cause preserved
func (*AppError) WithCause ¶
WithCause sets the underlying cause of the error and returns the receiver.
func (*AppError) WithDetail ¶
WithDetail sets a single RFC 9457 extension member and returns the receiver. The value type is a documented opaque-value exception (see AppError.Details); the value should be JSON-encodable.
func (*AppError) WithDetails ¶
WithDetails merges the provided RFC 9457 extension members into the error and returns the receiver. The value type is a documented opaque-value exception (see AppError.Details); values should be JSON-encodable.
Example ¶
package main
import (
"fmt"
"github.com/kbukum/gokit/errors"
)
func main() {
err := errors.NotFound("order", "abc").WithDetails(map[string]any{
"tenant": "acme",
})
fmt.Println(err.Code, err.Details["tenant"])
}
Output: NOT_FOUND acme
type ErrorCode ¶
type ErrorCode string
ErrorCode represents a machine-readable error code.
const ( ErrCodeServiceUnavailable ErrorCode = "SERVICE_UNAVAILABLE" // ErrCodeConnectionFailed indicates a failed connection to a service. ErrCodeConnectionFailed ErrorCode = "CONNECTION_FAILED" // ErrCodeTimeout indicates the request timed out. ErrCodeTimeout ErrorCode = "TIMEOUT" // ErrCodeRateLimited indicates the client is rate limited. ErrCodeRateLimited ErrorCode = "RATE_LIMITED" )
Connection/Availability errors (retryable)
const ( // ErrCodeNotFound indicates the requested resource was not found. ErrCodeNotFound ErrorCode = "NOT_FOUND" // ErrCodeAlreadyExists indicates the resource already exists. ErrCodeAlreadyExists ErrorCode = "ALREADY_EXISTS" // ErrCodeConflict indicates a conflict with the current state of the resource. ErrCodeConflict ErrorCode = "CONFLICT" )
Resource errors
const ( // ErrCodeInvalidInput indicates the input is invalid. ErrCodeInvalidInput ErrorCode = "INVALID_INPUT" // ErrCodeMissingField indicates a required field is missing. ErrCodeMissingField ErrorCode = "MISSING_FIELD" // ErrCodeInvalidFormat indicates a field has an invalid format. ErrCodeInvalidFormat ErrorCode = "INVALID_FORMAT" )
Validation errors
const ( ErrCodeUnauthorized ErrorCode = "UNAUTHORIZED" // ErrCodeForbidden indicates the request is forbidden. ErrCodeForbidden ErrorCode = "FORBIDDEN" // ErrCodeTokenExpired indicates the authentication token has expired. ErrCodeTokenExpired ErrorCode = "TOKEN_EXPIRED" // ErrCodeInvalidToken indicates the authentication token is invalid. ErrCodeInvalidToken ErrorCode = "INVALID_TOKEN" )
Authentication/Authorization errors
const ( // ErrCodeInternal indicates an internal server error. ErrCodeInternal ErrorCode = "INTERNAL_ERROR" // ErrCodeDatabaseError indicates a database error. ErrCodeDatabaseError ErrorCode = "DATABASE_ERROR" // ErrCodeExternalService indicates an error from an external service. ErrCodeExternalService ErrorCode = "EXTERNAL_SERVICE_ERROR" )
Internal errors
const ( // ErrCodeCanceled indicates the operation was canceled by the caller or system. ErrCodeCanceled ErrorCode = "CANCELED" )
Lifecycle errors
type ProblemDetail ¶
type ProblemDetail struct {
// Type is a URI identifying the problem type.
Type string `json:"type"`
// Title is a short human-readable summary of the problem type.
Title string `json:"title"`
// Status is the HTTP status code.
Status int `json:"status"`
// Detail is a human-readable explanation specific to this occurrence.
Detail string `json:"detail"`
// Instance is an optional URI identifying the specific occurrence.
Instance string `json:"instance,omitempty"`
// Code is the machine-readable error code.
Code ErrorCode `json:"code"`
// Retryable indicates whether the client may retry the request.
Retryable bool `json:"retryable"`
// Details carries RFC 9457 problem-detail extension members (arbitrary JSON).
// This is a deliberate, documented opaque-value exception to the no-any rule;
// see AppError.Details.
Details map[string]any `json:"details,omitempty"`
}
ProblemDetail is the RFC 9457 Problem Details response type.