When working with Nginx, you might have noticed that add_header
directives don't automatically apply to error responses (50x status codes). This behavior often catches developers off guard when they need to:
- Add debugging headers for error tracing
- Implement custom error handling logic
- Pass additional metadata to clients during failures
Nginx processes error responses differently from successful ones. The add_header
directive in regular location blocks won't affect error pages because:
# This won't work for error responses
location /example {
add_header X-Custom "value";
return 502;
}
Here are three effective approaches to solve this issue:
1. Using error_page with Named Locations
server {
error_page 502 @error502;
location @error502 {
add_header X-Custom-Error "502 Bad Gateway";
return 502;
}
location /test {
return 502;
}
}
2. The headers_more Module
For more advanced control, compile Nginx with headers_more
:
load_module modules/ngx_http_headers_more_filter_module.so;
http {
more_set_headers "X-Debug: backend_error";
server {
location / {
# Your regular config
}
}
}
3. Proxy Interception Method
When using Nginx as reverse proxy:
location / {
proxy_intercept_errors on;
error_page 502 = @handle_502;
proxy_pass http://backend;
}
location @handle_502 {
add_header X-Proxy-Error "502 occurred";
proxy_pass http://backend;
}
Here's how major companies implement custom error headers:
- Debugging:
X-Request-ID
for correlating logs - Security:
X-Block-Reason
for WAF triggers - Monitoring:
X-Backend-Status
for health checks
When implementing custom error headers:
- Keep header values small (under 1KB)
- Avoid complex Lua scripts for simple headers
- Cache static error responses when possible
When working with Nginx, many developers encounter a puzzling behavior: custom headers added via add_header
directives don't appear in 5xx error responses. This happens because Nginx handles error responses differently from successful ones.
In your example:
location /mediocregopheristhecoolest {
add_header X-Test "blahblahblah";
return 502;
}
The header won't appear because Nginx processes the return
directive before evaluating headers for error responses. This is by design - error responses use separate internal handlers.
The proper way to add headers to error responses is through the error_page
directive combined with a named location:
server {
error_page 502 @error_502;
location @error_502 {
add_header X-Test "blahblahblah";
return 502;
}
location /test {
return 502;
}
}
For comprehensive error handling across your server:
http {
# Define error handlers
error_page 500 502 503 504 @server_errors;
location @server_errors {
add_header X-Error-Type "5xx Server Error";
add_header X-Request-ID $request_id;
add_header Retry-After "30";
# Preserve the original error code
proxy_intercept_errors on;
return $status;
}
}
1. Headers only appear when Nginx generates the error response directly
2. For proxy_pass errors, you'll need additional configuration
3. Some older Nginx versions (pre-1.7.5) might require different syntax
Use this curl command to verify headers appear:
curl -I http://yourserver/test-error-path