RespKit

Error mapping

RespKit classifies errors by their type and identity, including errors wrapped with %w. It uses errors.Is and errors.As; it does not infer meaning from the text returned by Error().

Built-in mappings

Go errorPublic codeHTTP status
resp.ErrBadRequestBAD_REQUEST400
resp.ErrUnauthorizedUNAUTHORIZED401
resp.ErrForbiddenFORBIDDEN403
resp.ErrNotFoundRESOURCE_NOT_FOUND404
resp.ErrConflictRESOURCE_CONFLICT409
resp.ErrValidationVALIDATION_FAILED422
resp.ErrRateLimitedRATE_LIMITED429
resp.ErrUnavailableSERVICE_UNAVAILABLE503
Unrecognized errorINTERNAL_ERROR500

Malformed JSON and JSON with an incompatible value type map to BAD_REQUEST. PostgreSQL SQLSTATE 23505 maps to RESOURCE_ALREADY_EXISTS (409) without requiring a database driver. Other database conditions remain unmapped in the core because their HTTP meaning depends on the application. The optional database integration guide describes the pgx adapter.

Create an application error

Use a stable public code and a status that matches the domain condition. Attach the original error as a cause for server-side inspection:

err := resp.NewError(
	"PAYMENT_DECLINED",
	http.StatusUnprocessableEntity,
	resp.WithCause(errFromPaymentProvider),
)
return resp.Fail(ctx, err)

Public codes should use uppercase letters, numbers, and underscores. A cause is available to logging and diagnostics but is not serialized into the response. Invalid code or status values fall back to a safe internal error.

Add validation details

Field details help clients identify values to fix. Include only information that is safe to return:

err := resp.NewError(
	"VALIDATION_FAILED",
	http.StatusUnprocessableEntity,
	resp.WithDetails(
		resp.FieldError{Field: "email", Code: "FIELD_REQUIRED"},
		resp.FieldError{
			Field:  "name",
			Code:   "MIN_LENGTH",
			Params: map[string]string{"min": "3"},
		},
	),
)
return resp.Fail(ctx, err)

Do not put credentials, database queries, or other sensitive values in error details or translation parameters.

Map a third-party error

Add a mapper when a dependency exposes a typed error with a meaning understood by the application. Return false when the mapper does not recognize an error:

func mapPaymentError(err error) (resp.Definition, bool) {
	var paymentErr *PaymentError
	if !errors.As(err, &paymentErr) {
		return resp.Definition{}, false
	}

	return resp.Definition{
		Code:   "PAYMENT_DECLINED",
		Status: http.StatusUnprocessableEntity,
	}, true
}

api, err := resp.New(resp.WithMapper("payment", mapPaymentError))
if err != nil {
	return err
}

return api.Fail(ctx, errFromPaymentProvider)

Configure mappers when creating an engine. Avoid mapping ambiguous errors based on their message text. For integrations tied to a specific database or driver, keep the dependency in a separate optional module.

On this page