Configuration: JSON error responses
This page documents the json_errors directive for generating structured JSON error responses instead of HTML. This is useful for RESTful API endpoints where clients expect machine-readable error bodies.
Directives
JSON errors
json_errors <enabled: bool>(http-jsonerror)- When
true, HTTP error responses (4xx, 5xx) are returned with a JSON body instead of an HTML error page. Default:false
- When
Block options
| Option | Arguments | Description | Default |
|---|---|---|---|
format | "problem" | "simple" | Output format. "problem" uses RFC 9457 Problem Details (application/problem+json); "simple" uses plain JSON (application/json). | "problem" |
type_uri | <string> | URI for the type field in RFC 9457 format. The {status} placeholder is replaced with the HTTP status code. | "about:blank" |
trace_id | <bool> | Include the request’s trace ID in the response when available. | true |
Configuration example:
example.com {
json_errors
}RFC 9457 Problem Details format
With format "problem" (default), responses use Content-Type: application/problem+json and follow the RFC 9457 structure:
example.com {
json_errors {
type_uri "https://api.example.com/errors/{status}"
}
}Example response for a 404 error:
{
"type": "https://api.example.com/errors/404",
"title": "Not Found",
"status": 404,
"detail": "The requested resource wasn't found.",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}Simple JSON format
With format "simple", responses use Content-Type: application/json with a minimal structure:
example.com {
json_errors {
format "simple"
}
}Example response:
{
"error": "Not Found",
"status": 404,
"detail": "The requested resource wasn't found.",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}Scope to API paths
Use location blocks to enable JSON errors only for API endpoints:
example.com {
location /api {
json_errors {
type_uri "https://api.example.com/errors/{status}"
}
}
# Other paths get standard HTML error pages
}Scoping
The json_errors directive can be placed at different configuration levels:
- Host level — applies to all requests for that host
locationblock — applies only to requests matching that path prefixif/if_notblocks — applies conditionally based on a matcher
example.com {
# All errors are JSON for this host
json_errors
match BLOG {
request.uri.path ~ "^/blog($|/)"
}
if BLOG {
# Override: HTML error pages for the blog
json_errors false
}
}Interaction with error pages
When json_errors is enabled, the JSON error stage runs before the error_page stage (which serves custom HTML error pages). This means:
- JSON errors take precedence over
error_pagefile-based error pages - The built-in HTML error page fallback is never reached when JSON errors are enabled
- To use both HTML and JSON error pages for different paths, use
locationblocks
Observability
Trace spans
The stage sets the following attributes on its ferron.stage.json_error span:
| Attribute | Type | Description |
|---|---|---|
ferron.json_error.format | string | Output format ("problem" or "simple") |
ferron.json_error.status_code | i64 | HTTP status code of the error response |