Documentation
¶
Overview ¶
Package errors is the transport-agnostic error substrate. An AppError value carries a canonical Code plus the seeded HTTP and gRPC statuses, and renders to both problem+json (via pkg/errors/fiber) and status+errdetails (via pkg/errors/grpc). The core imports only google.golang.org/grpc/codes as a transport-adjacent leaf; framework-error mapping lives in the renderers.
Index ¶
- type AppError
- func AlreadyExists(msg string) *AppError
- func FailedPrecondition(msg string) *AppError
- func FromError(err error) *AppError
- func Internal(msg string) *AppError
- func InvalidArgument(msg string) *AppError
- func New(code Code, msg string) *AppError
- func NotFound(msg string) *AppError
- func PermissionDenied(msg string) *AppError
- func Unauthenticated(msg string) *AppError
- func Unavailable(msg string) *AppError
- func Validation(msg string) *AppError
- type Code
- type FieldViolation
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AppError ¶
type AppError struct {
Code Code // canonical classifier
Message string // human-safe, client-visible message
HTTP int // seeded from Code; the fiber renderer's status
GRPC codes.Code // seeded from Code; the gRPC renderer's status code
Meta map[string]string // rendered as errdetails.ErrorInfo.Metadata
Fields []FieldViolation // rendered as invalid_params / errdetails.BadRequest
// contains filtered or unexported fields
}
AppError is the transport-agnostic error substrate. One value renders to both problem+json (fiber) and status+errdetails (gRPC). Construct via the code constructors; enrich via the With* builders. The zero value is not valid.
func AlreadyExists ¶
AlreadyExists builds an ALREADY_EXISTS AppError.
func FailedPrecondition ¶
FailedPrecondition builds a FAILED_PRECONDITION AppError.
func FromError ¶
FromError normalizes any error into a non-nil *AppError (nil in -> nil out). Precedence:
- errors.As(*AppError): return it unchanged (already normalized).
- oops error (has Code()/Context()): map its Code() to a canonical Code when it matches, else CodeInternal; lift Context() into Meta (stringified); preserve the oops error as cause.
- otherwise: Internal("internal error") with err kept as cause.
Framework errors (fiber.Error, grpc status) are NOT mapped here — that lives in the transport renderers so the core stays free of fiber/genproto imports.
func InvalidArgument ¶
InvalidArgument builds an INVALID_ARGUMENT AppError.
func New ¶
New builds an AppError for code with the given message, seeding HTTP and GRPC from the mapping table.
func PermissionDenied ¶
PermissionDenied builds a PERMISSION_DENIED AppError.
func Unauthenticated ¶
Unauthenticated builds an UNAUTHENTICATED AppError.
func Unavailable ¶
Unavailable builds an UNAVAILABLE AppError.
func Validation ¶
Validation builds a VALIDATION AppError (field-enumerating; Phase 6 producer).
func (*AppError) Error ¶
Error returns Message only (never the cause / never Meta) so an accidental %v never leaks internals into a log line that reaches a client.
func (*AppError) WithCause ¶
WithCause attaches the wrapped origin error (surfaced via Unwrap; kept off the wire) and returns e for chaining.
type Code ¶
type Code string
Code is the stable, transport-agnostic error classifier. It is the value rendered as problem+json `code`, the errdetails.ErrorInfo `Reason`, and the `urn:lakta:error:{code}` type URI. Treat the string values as wire contract.
const ( CodeNotFound Code = "NOT_FOUND" CodeInvalidArgument Code = "INVALID_ARGUMENT" CodeValidation Code = "VALIDATION" CodeUnauthenticated Code = "UNAUTHENTICATED" CodePermissionDenied Code = "PERMISSION_DENIED" CodeAlreadyExists Code = "ALREADY_EXISTS" CodeFailedPrecondition Code = "FAILED_PRECONDITION" CodeInternal Code = "INTERNAL" )
Canonical codes. Each seeds a fixed (HTTP, codes.Code) pair via statusFor; constructors read that mapping so a code always renders identically.
Code HTTP gRPC (codes.Code) NOT_FOUND 404 NotFound INVALID_ARGUMENT 400 InvalidArgument VALIDATION 400 InvalidArgument UNAUTHENTICATED 401 Unauthenticated PERMISSION_DENIED 403 PermissionDenied ALREADY_EXISTS 409 AlreadyExists FAILED_PRECONDITION 400 FailedPrecondition UNAVAILABLE 503 Unavailable INTERNAL 500 Internal
type FieldViolation ¶
type FieldViolation struct {
Field string // dotted/bracketed path, e.g. "user.email" or "items[0].qty"
Description string // failing rule, e.g. "required", "email", "min"
}
FieldViolation names one invalid input field and why it failed. Populated only by validation (Phase 6); auth (Phase 11) must never set it.