Error Handling
Sentinel errors and how Relay surfaces problems.
Relay defines a set of sentinel errors in the root package. Use errors.Is to check for specific conditions.
Sentinel errors
var (
ErrNoStore = errors.New("relay: store is required")
ErrEndpointNotFound = errors.New("relay: endpoint not found")
ErrEventTypeNotFound = errors.New("relay: event type not found")
ErrEventTypeDeprecated = errors.New("relay: event type is deprecated")
ErrPayloadValidationFailed = errors.New("relay: payload validation failed")
ErrDuplicateIdempotencyKey = errors.New("relay: duplicate idempotency key")
ErrEndpointDisabled = errors.New("relay: endpoint is disabled")
ErrStoreClosed = errors.New("relay: store is closed")
ErrMigrationFailed = errors.New("relay: migration failed")
ErrDLQNotFound = errors.New("relay: dlq entry not found")
ErrDeliveryNotFound = errors.New("relay: delivery not found")
ErrEventNotFound = errors.New("relay: event not found")
)Checking errors
err := r.Send(ctx, evt)
if errors.Is(err, relay.ErrEventTypeNotFound) {
// event type not registered in the catalog
}Wrapping convention
Subsystems wrap the sentinel with fmt.Errorf and %w:
return fmt.Errorf("%w: %s", ErrEventTypeNotFound, evt.Type)Validation errors
The endpoint service returns *endpoint.ValidationError for invalid input:
var valErr *endpoint.ValidationError
if errors.As(err, &valErr) {
log.Printf("invalid %s: %s", valErr.Field, valErr.Message)
}Idempotency
Duplicate idempotency keys are not treated as errors. When Send() encounters a duplicate, it returns nil (no-op success).