zoobzio December 15, 2025 Edit this page

Errors Reference

Complete reference for rocco error types and detail structures.

Error Interface

ErrorDefinition

type ErrorDefinition interface {
    error
    Code() string
    Status() int
    Message() string
    DetailsAny() any
    DetailsMeta() sentinel.Metadata
}
MethodDescription
Error()Returns error message (implements error interface)
Code()Returns error code (e.g., "NOT_FOUND")
Status()Returns HTTP status code
Message()Returns human-readable message
DetailsAny()Returns details as any type
DetailsMeta()Returns sentinel metadata for OpenAPI schema generation

Creating Custom Errors

NewError

func NewError[D any](code string, status int, message string) *Error[D]

Creates a new error type with typed details.

ParameterTypeDescription
Dtype parameterDetails type
codestringError code (e.g., "TEAPOT")
statusintHTTP status code
messagestringDefault message

Example

type TeapotDetails struct {
    TeaType string `json:"tea_type" description:"Type of tea"`
}

var ErrTeapot = rocco.NewError[TeapotDetails]("TEAPOT", 418, "I'm a teapot")

// Usage
return Output{}, ErrTeapot.WithDetails(TeapotDetails{TeaType: "Earl Grey"})

Built-in Errors

ErrBadRequest

var ErrBadRequest = NewError[BadRequestDetails]("BAD_REQUEST", 400, "bad request")

Status: 400 Bad Request

Details:

type BadRequestDetails struct {
    Reason string `json:"reason,omitempty" description:"Reason for bad request"`
}

ErrUnauthorized

var ErrUnauthorized = NewError[UnauthorizedDetails]("UNAUTHORIZED", 401, "unauthorized")

Status: 401 Unauthorized

Details:

type UnauthorizedDetails struct {
    Reason string `json:"reason,omitempty" description:"Reason for unauthorized"`
}

ErrForbidden

var ErrForbidden = NewError[ForbiddenDetails]("FORBIDDEN", 403, "forbidden")

Status: 403 Forbidden

Details:

type ForbiddenDetails struct {
    Reason string `json:"reason,omitempty" description:"Reason for forbidden"`
}

ErrNotFound

var ErrNotFound = NewError[NotFoundDetails]("NOT_FOUND", 404, "not found")

Status: 404 Not Found

Details:

type NotFoundDetails struct {
    Resource string `json:"resource,omitempty" description:"Resource type that was not found"`
}

ErrConflict

var ErrConflict = NewError[ConflictDetails]("CONFLICT", 409, "conflict")

Status: 409 Conflict

Details:

type ConflictDetails struct {
    Reason string `json:"reason,omitempty" description:"What caused the conflict"`
}

ErrPayloadTooLarge

var ErrPayloadTooLarge = NewError[PayloadTooLargeDetails]("PAYLOAD_TOO_LARGE", 413, "payload too large")

Status: 413 Payload Too Large

Details:

type PayloadTooLargeDetails struct {
    MaxSize int64 `json:"max_size,omitempty" description:"Maximum allowed payload size in bytes"`
}

ErrUnprocessableEntity

var ErrUnprocessableEntity = NewError[UnprocessableEntityDetails]("UNPROCESSABLE_ENTITY", 422, "unprocessable entity")

Status: 422 Unprocessable Entity

Details:

type UnprocessableEntityDetails struct {
    Reason string `json:"reason,omitempty" description:"Reason entity is unprocessable"`
}

ErrValidationFailed

var ErrValidationFailed = NewError[ValidationDetails]("VALIDATION_FAILED", 422, "validation failed")

Status: 422 Unprocessable Entity

Details:

type ValidationDetails struct {
    Fields []ValidationFieldError `json:"fields" description:"List of field validation errors"`
}

type ValidationFieldError struct {
    Field   string `json:"field" description:"Field name that failed validation"`
    Message string `json:"message" description:"Description of the validation failure"`
}

ErrTooManyRequests

var ErrTooManyRequests = NewError[TooManyRequestsDetails]("TOO_MANY_REQUESTS", 429, "too many requests")

Status: 429 Too Many Requests

Details:

type TooManyRequestsDetails struct {
    RetryAfter int `json:"retry_after,omitempty" description:"Seconds until retry is allowed"`
}

ErrInternalServer

var ErrInternalServer = NewError[InternalServerDetails]("INTERNAL_SERVER_ERROR", 500, "internal server error")

Status: 500 Internal Server Error

Details:

type InternalServerDetails struct {
    Reason string `json:"reason,omitempty" description:"Internal error context"`
}

ErrNotImplemented

var ErrNotImplemented = NewError[NotImplementedDetails]("NOT_IMPLEMENTED", 501, "not implemented")

Status: 501 Not Implemented

Details:

type NotImplementedDetails struct {
    Feature string `json:"feature,omitempty" description:"Feature not implemented"`
}

ErrServiceUnavailable

var ErrServiceUnavailable = NewError[ServiceUnavailableDetails]("SERVICE_UNAVAILABLE", 503, "service unavailable")

Status: 503 Service Unavailable

Details:

type ServiceUnavailableDetails struct {
    Reason string `json:"reason,omitempty" description:"Reason for unavailability"`
}

Error Response Format

All errors serialize to:

{
  "code": "ERROR_CODE",
  "message": "Human-readable message",
  "details": {
    // Optional typed details
  }
}
FieldTypeDescription
codestringMachine-readable error code
messagestringHuman-readable message
detailsobjectOptional structured details (omitted if nil)

Usage Patterns

Simple Error

return Output{}, rocco.ErrNotFound

Response:

{
  "code": "NOT_FOUND",
  "message": "not found"
}

With Custom Message

return Output{}, rocco.ErrNotFound.WithMessage("user not found")

Response:

{
  "code": "NOT_FOUND",
  "message": "user not found"
}

With Details

return Output{}, rocco.ErrNotFound.WithDetails(rocco.NotFoundDetails{
    Resource: "user",
})

Response:

{
  "code": "NOT_FOUND",
  "message": "not found",
  "details": {
    "resource": "user"
  }
}

With Cause (for logging)

return Output{}, rocco.ErrInternalServer.WithCause(err)

The cause is logged but not exposed to clients.

Combined

return Output{}, rocco.ErrConflict.
    WithMessage("email already registered").
    WithDetails(rocco.ConflictDetails{
        Reason: "email address is already in use",
    })

See Also