Nginx

Nginx 500 Internal Server Error Without Any Error Log Output

· by DebuggedIt

Quick answer

A 500 error with nothing showing up in Nginx's error log doesn't mean Nginx has no idea what happened — it usually means either the log level is set too...

A 500 error with nothing showing up in Nginx's error log doesn't mean Nginx has no idea what happened — it usually means either the log level is set too restrictively to capture the relevant detail, the error is being logged somewhere other than where you're looking, or the 500 is actually coming from your backend application rather than Nginx itself.

The Problem

A request fails with a 500 status, but checking the expected Nginx error log shows nothing relevant around the time of the failure:

tail -f /var/log/nginx/error.log
# no new entries appear when the 500 error occurs

Why It Happens

Several distinct reasons can produce a 500 with no corresponding, obvious Nginx error log entry:

  • Nginx's configured error_log level is set to a level that excludes the specific severity of the error being generated — by default, some configurations only log error level and above, while certain issues might only be logged at a more verbose level like warn or notice
  • The 500 response is actually being generated by your backend application, not by Nginx itself, and Nginx is simply passing that response through unchanged — in this case, the relevant error detail lives in your application's own logs, not Nginx's
  • You're checking the wrong log file entirely — a server block might have its own specific error_log directive pointing to a different file than the global default you're monitoring, particularly common in multi-site Nginx configurations
  • The error is being logged, but to a location or in a format you're not currently checking — some setups redirect logs to syslog, a centralized logging service, or a different rotation-managed file than the one you're actively tailing

The Fix

First, confirm whether the 500 is coming from Nginx itself or being passed through from your backend, by checking your backend application's own logs directly for the same request timestamp:

# Check your application server's own logs, not just Nginx's
journalctl -u your-app-service --since "5 minutes ago"

If your backend's own logs show a clear error or exception around the same time, the 500 originated there, and Nginx's error log being empty is entirely expected — Nginx isn't generating this specific error, just relaying it.

If you need to confirm this more directly, temporarily increase Nginx's log verbosity to capture more detail, which can reveal whether Nginx itself logged anything at all about the request, even at a lower severity than you were originally checking for:

error_log /var/log/nginx/error.log debug;

Be aware debug level produces a very large volume of output and should only be enabled temporarily for active troubleshooting, then reverted, since leaving it enabled in production generates excessive log volume and can itself become a performance/disk-space concern.

Confirm you're checking the correct log file for the specific server block actually handling the failing request — if a server block has its own explicit error_log directive, that overrides the global default for requests handled by that specific block:

grep -r error_log /etc/nginx/

This surfaces every error_log directive across your configuration, revealing whether the specific site/server block generating the 500 is actually logging to a different file than the one you were originally monitoring.

Add explicit, more detailed access logging temporarily, capturing more request context (including upstream response details for proxied requests) that can help correlate the specific failing request with whatever log entries do exist:

log_format detailed '$remote_addr - $status - $upstream_status - $request - $upstream_addr - $request_time';
access_log /var/log/nginx/detailed.log detailed;

The $upstream_status and $upstream_addr variables specifically are useful here, since they reveal what your backend actually returned and which specific backend instance handled the request, both very relevant for understanding whether the 500 originated with the backend versus Nginx's own processing.

Still Not Working?

If you've confirmed the request isn't reaching your backend at all (ruling out an application-level error), and Nginx's own logs at debug level still show nothing informative around the specific failing request, check whether the 500 might actually be generated by an intermediate layer in front of Nginx — a CDN, a load balancer, or a WAF (Web Application Firewall) can generate their own 500-status responses for reasons entirely unrelated to your Nginx or backend configuration at all, and would have no reason to appear in your Nginx logs, since Nginx never actually received or processed the original request that triggered that specific 500 response.