Files
xerrors/code.go
Rene Nochebuena 3cc36801a1 feat(xerrors): initial stable release v0.9.0
Structured application errors with typed codes, cause chaining, key-value context fields, and zero-import logz enrichment bridge.

What's included:
- `*Err` type implementing error, errors.Unwrap, json.Marshaler, ErrorCode(), and ErrorContext()
- Twelve typed Code constants aligned with gRPC canonical status names
- New / Wrap factory constructors plus InvalidInput / NotFound / Internal convenience constructors
- Builder methods WithContext and WithError for attaching structured fields and causes
- Duck-typed ErrorCode() / ErrorContext() bridge so logz auto-enriches log records without an import

Tested-via: todo-api POC integration
Reviewed-against: docs/adr/
2026-03-18 13:09:31 -06:00

98 lines
3.7 KiB
Go

package xerrors
// Code is the machine-readable error category.
// Wire values are stable across versions and are identical to gRPC status code names.
// HTTP mapping is the responsibility of the transport layer, not this package.
type Code string
const (
// ErrInvalidInput indicates the request contains malformed or invalid data.
// The caller should fix the input before retrying.
ErrInvalidInput Code = "INVALID_ARGUMENT"
// ErrUnauthorized indicates the request lacks valid authentication credentials.
// The caller should authenticate and retry.
ErrUnauthorized Code = "UNAUTHENTICATED"
// ErrPermissionDenied indicates the authenticated caller lacks permission for the operation.
// Authentication is not the issue — the caller is authenticated but not authorised.
ErrPermissionDenied Code = "PERMISSION_DENIED"
// ErrNotFound indicates the requested resource does not exist.
ErrNotFound Code = "NOT_FOUND"
// ErrAlreadyExists indicates a resource with the same identifier already exists.
// Use for creation conflicts (e.g. duplicate email on sign-up).
// For state-based conflicts not related to creation, use ErrPreconditionFailed.
ErrAlreadyExists Code = "ALREADY_EXISTS"
// ErrGone indicates the resource existed but has been permanently removed.
// Unlike ErrNotFound, this signals the caller should not retry — the resource
// is gone for good (e.g. a soft-deleted record that has been purged).
ErrGone Code = "GONE"
// ErrPreconditionFailed indicates the operation was rejected because a required
// condition was not met. The input is valid but a business rule blocks the action
// (e.g. "cannot delete an account with active subscriptions", or an optimistic-lock
// mismatch). Different from ErrAlreadyExists (duplicate creation) and
// ErrInvalidInput (bad data).
ErrPreconditionFailed Code = "FAILED_PRECONDITION"
// ErrRateLimited indicates the caller has exceeded a rate limit or exhausted a quota.
ErrRateLimited Code = "RESOURCE_EXHAUSTED"
// ErrCancelled indicates the operation was cancelled, typically because the caller
// disconnected or the request context was cancelled.
// Useful for translating context.Canceled to a structured error at service boundaries.
ErrCancelled Code = "CANCELLED"
// ErrInternal indicates an unexpected server-side failure.
// This code should not be used when a more specific code applies.
ErrInternal Code = "INTERNAL"
// ErrNotImplemented indicates the requested operation has not been implemented.
ErrNotImplemented Code = "UNIMPLEMENTED"
// ErrUnavailable indicates the service is temporarily unable to handle requests.
// The caller may retry with backoff.
ErrUnavailable Code = "UNAVAILABLE"
// ErrDeadlineExceeded indicates the operation timed out before completing.
ErrDeadlineExceeded Code = "DEADLINE_EXCEEDED"
)
// Description returns a human-readable description for the code.
// Unknown codes return their raw string value.
func (c Code) Description() string {
switch c {
case ErrInvalidInput:
return "Invalid input provided"
case ErrUnauthorized:
return "Authentication required"
case ErrPermissionDenied:
return "Insufficient permissions"
case ErrNotFound:
return "Resource not found"
case ErrAlreadyExists:
return "Resource already exists"
case ErrGone:
return "Resource permanently deleted"
case ErrPreconditionFailed:
return "Precondition not met"
case ErrRateLimited:
return "Rate limit exceeded"
case ErrCancelled:
return "Request cancelled"
case ErrInternal:
return "Internal error"
case ErrNotImplemented:
return "Not implemented"
case ErrUnavailable:
return "Service unavailable"
case ErrDeadlineExceeded:
return "Deadline exceeded"
default:
return string(c)
}
}