Error Handling
Okapi provides a flexible error handling system with built-in support for standard JSON errors, custom error formats, and RFC 7807 Problem Details.
Note on error details in production
DefaultErrorHandlerputs the underlying error's text into thedetailsfield of the response, and middleware such as the JWT authenticator passes its internal error through. Clients therefore learn exactly why a request failed — with a JWKS-backed setup that can include the JWKS URL and the network error behind it, which is useful reconnaissance against an internal endpoint.If that matters for your deployment, install a custom
ErrorHandlerthat logs the error server-side and omitsdetailsfrom the response. See Custom Error Handlers below.
Quick Start
Use c.Abort* methods to immediately stop request processing and return an error response:
o := okapi.Default()
o.Post("/books", func(c okapi.C) error {
book := &Book{}
if err := c.Bind(book); err != nil {
return c.AbortBadRequest("Invalid request body", err)
}
// ... handle valid request
return c.Created(book)
})
Response:
{
"code": 400,
"message": "Invalid request body",
"details": "field Name is required",
"timestamp": "2026-02-09T21:34:17.290908+01:00"
}
Available Error Methods
Okapi provides convenience methods for common HTTP error codes:
| Method | Status Code | Use Case |
|---|---|---|
AbortBadRequest(msg, err) | 400 | Validation errors, malformed requests |
AbortUnauthorized(msg, err) | 401 | Missing or invalid authentication |
AbortForbidden(msg, err) | 403 | Insufficient permissions |
AbortNotFound(msg, err) | 404 | Resource not found |
AbortConflict(msg, err) | 409 | Resource conflicts |
AbortInternalServerError(msg, err) | 500 | Unexpected server errors |
| And more |
For other status codes, use the generic method:
return c.AbortWithError(http.StatusTeapot, err)
Custom Error Handlers
Override the default error format by providing a custom error handler:
o := okapi.Default().With(
okapi.WithErrorHandler(func(c *okapi.Context, code int, message string, err error) error {
return c.JSON(code, map[string]any{
"success": false,
"error": map[string]any{
"code": code,
"message": message,
"details": err.Error(),
},
})
}),
)
Response:
{
"success": false,
"error": {
"code": 400,
"message": "Invalid request body"
}
}
RFC 7807 Problem Details
For APIs requiring standards-compliant error responses, Okapi supports RFC 7807 Problem Details.
Basic Setup
o := okapi.Default()
o.WithSimpleProblemDetailErrorHandler()
Response (Content-Type: application/problem+json):
{
"type": "about:blank",
"title": "Bad Request",
"status": 400,
"detail": "field Name is required",
"instance": "/books"
}
Advanced Configuration
Customize the Problem Details output with additional fields and options:
o := okapi.Default()
o.WithProblemDetailErrorHandler(&okapi.ErrorHandlerConfig{
Format: okapi.ErrorFormatProblemJSON,
TypePrefix: "https://api.example.com/errors/",
IncludeInstance: true,
IncludeTimestamp: true,
CustomFields: map[string]any{
"api_version": "v1.0.0",
"support_url": "https://support.example.com",
},
})
Response:
{
"type": "https://api.example.com/errors/bad-request",
"title": "Bad Request",
"status": 400,
"detail": "field Name is required",
"instance": "/books",
"timestamp": "2026-02-09T21:42:49+01:00",
"api_version": "v1.0.0",
"support_url": "https://support.example.com"
}
Configuration Options
| Option | Description |
|---|---|
Format | Response format (see below) |
TypePrefix | Base URL for error type URIs |
IncludeInstance | Include the request path in responses |
IncludeTimestamp | Add a timestamp to each error |
CustomFields | Additional fields to include in all error responses |
Supported Formats
| Format | Content-Type | Description |
|---|---|---|
ErrorFormatProblemJSON | application/problem+json | RFC 7807 JSON format (default) |
ErrorFormatProblemXML | application/problem+xml | RFC 7807 XML format |
Example with XML format:
o.WithProblemDetailErrorHandler(&okapi.ErrorHandlerConfig{
Format: okapi.ErrorFormatProblemXML,
})
Response (Content-Type: application/problem+xml):
<?xml version="1.0" encoding="UTF-8"?>
<problem xmlns="urn:ietf:rfc:7807">
<type>about:blank</type>
<title>Bad Request</title>
<status>400</status>
<detail>field Name is required</detail>
<instance>/books</instance>
</problem>