Recently I came across a 502 Bad Gateway on a WordPress REST endpoint, which I had to fix:
Stack: Nginx + PHP-FPM behind CloudFront.
At first it looked like the usual “proxy header size too big” issue. Nginx error logs also pointed to it:
upstream sent too big header while reading response header from upstream
I bumped the FastCGI buffers (a lot!) but the 502 stayed. So something was still sending an unusually large response header. While looking in browser console I was not getting anything big in response header for that REST endpoint.
Why DevTools didn’t show the full headers?
That’s expected: Nginx failed while reading the upstream (PHP-FPM) headers, so it never forwarded those headers to CloudFront or the browser. CloudFront then generated its own 502 with its own small headers. DevTools can only show what it actually receives—the oversized upstream headers never made it that far.
How I finally saw the real headers?
Because the browser couldn’t show them, I logged them inside WordPress before they reached Nginx. With the help of AI created an MU plugin at wp-content/mu-plugins/log-rest-headers.php
<?php
/*
Plugin Name: Log REST headers (safe)
Description: Logs top response headers for a specific REST route, excluding Set-Cookie.
*/
add_action('rest_api_init', function () {
add_filter('rest_pre_serve_request', function ($served, $result, $request) {
$route = $request->get_route();
if (strpos($route, '/wp-json/{route}') === 0) {
$headers = headers_list();
$total = 0; $lines = [];
foreach ($headers as $h) {
if (stripos($h, 'Set-Cookie:') === 0) { continue; } // avoid logging cookies
$total += strlen($h);
// cap very long lines for safety
$display = (strlen($h) > 300) ? substr($h, 0, 300).'…' : $h;
$lines[] = strlen($h).' '.$display;
}
$log = WP_CONTENT_DIR . '/rest-headers.log';
@file_put_contents($log,
'['.date('c')."] total={$total} bytes\n".implode("\n", array_slice($lines,0,50))."\n\n",
FILE_APPEND
);
}
return $served;
}, 9999, 3);
});
After hitting the endpoint (logged-in), the log showed ~726 KB of headers with hundreds of lines like
X-QM-php_errors-count: 1039
X-QM-php_errors-error-1: {"type":"warning", ... "component":"Plugin: ******"}
Bingo.
Root cause…
- A plugin was throwing a lot of PHP warnings/deprecations on this route.
- The Query Monitor plugin collected those errors and emitted one header per error:
X-QM-php_errors-error-*. - The sheer number of these headers made the upstream response header enormous → Nginx failed to read it → CloudFront 502.
The fix:
- Quick Fix
- Deactivated query_monitor plugin and verified that REST endpoint is working fine now.
- Clean up the underlying warnings
- Work on the code side for the plugin to remove warnings.

Leave a Reply