How to Add Custom Headers to Nginx 50x Error Responses: A Complete Guide for Developers


2 views

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:

  1. Keep header values small (under 1KB)
  2. Avoid complex Lua scripts for simple headers
  3. 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