502, 504 and other Nginx errors: causes and fixes
The three-digit number you see in the browser is the HTTP status code that reports the outcome of the request. Codes starting with 4 describe a problem with the request itself (wrong address, no permission, file too large); codes starting with 5 describe a problem on the server side. When Nginx works as a reverse proxy, it generates some of these codes itself and passes others on exactly as it received them from the application behind it.
Half of solving the problem is knowing where the error arises: in Nginx itself, on the connection between Nginx and the backend server, or inside the application? This guide takes the most common codes one by one: what each means, why it happens, how to diagnose it and how to fix it.
In brief
- 502: Nginx could not reach the backend or got an invalid response. 504: the backend did not answer in time.
- The first place to look is the Nginx error log; the cause is usually stated in a single line.
- 413 is the body size limit; 499 means the client closed the connection without waiting.
- Raising the timeout is the last resort; find the cause of the slowness first.
Tip
If the error page says "nginx" at the bottom, the response was generated by Nginx. If you see an error page in your application's own design, the code came from the application; check the application's log.
On this page
Where does the error arise and how is it diagnosed?
-
Work out where the error arises
A request passes three stations: the client (browser), Nginx and the backend (the process that runs the application, such as PHP-FPM, Node.js or Python). Each code points to one of them:
- Nginx's own decision: 403, 404 (for static files), 413. The request may never have reached the backend.
- Between Nginx and the backend: 502 and 504. Nginx is running but cannot get a proper response from the application behind it.
- Inside the application: 500, and any 404 or 403 returned by the application. Nginx passes this response on unchanged.
- On the client side: 499. The client closed the connection without waiting for the response.
: Enlarge -
Read the logs
Nginx keeps two logs. The access log (access.log) records every request together with its status code: which address, when, and with which code did it end? The error log (error.log) states the cause of the problem. In most installations both are under
/var/log/nginx/; hosting control panels may keep per-site logs in a different folder. The exact path is given by theaccess_loganderror_logdirectives in the configuration.Bash# Last 50 lines of the error log (this is the path in most installations) sudo tail -n 50 /var/log/nginx/error.log # Follow the log live; reproduce the error in the browser meanwhile sudo tail -f /var/log/nginx/error.log # Last lines of the access log: request, status code, size sudo tail -n 50 /var/log/nginx/access.logA line in the error log usually contains the problem itself (e.g.
connect() failed), the address of the request and the backend address beginning withupstream:. That line tells you which cause to look at in the sections below. -
Tell 502 and 504 apart
Both say "there is a problem with the backend", but they describe different things. 502 means that Nginx could not connect to the backend or that the connection broke before a response arrived; the error usually appears immediately. 504 means that the connection was established but the response did not arrive within the timeout; the error appears after the waiting time has elapsed (60 seconds by default).
: Enlarge -
Diagnose in order
- Note the code, the address and the time. Does the error occur on every request, only on a particular page, or only at busy times?
- Look at that time in the error log. If there is no line, the code most probably came from the application.
- Is the backend up? Check the status of the service.
- Try the backend while bypassing Nginx. From inside the server, send a request straight to the application's address: does it answer, and how long does it take?
- Review the configuration. Are the address and port correct, are the limits and timeouts suitable, are the file permissions sufficient?
- Fix, test, reload.
Bash# Is Nginx running? sudo systemctl status nginx # Is the backend service running? (replace the service name with your own) sudo systemctl status php-fpm # Try the backend while bypassing Nginx (for applications listening over HTTP) curl -I http://127.0.0.1:3000/ # Try the same address through Nginx curl -I http://example.com/The service name depends on the system; the name of the PHP-FPM service often includes a version number. Take the backend address from the
proxy_passline in your own configuration.
: Enlarge -
Identify the code and go to its section
The table below summarises the most common codes; each is covered in detail in the sections that follow.
Code Meaning Most common cause Where to look first 502 Bad Gateway: no valid response from the backend Application not running, wrong address or socket error.log, service status 504 Gateway Timeout: the backend did not answer in time Slow query or task, short timeout error.log, application log 413 Request Entity Too Large: the request body is too big The client_max_body_sizelimitConfiguration 499 The client closed the connection (specific to Nginx) Slow response, impatient client or a timeout in the layer in front access.log 403 Forbidden: access not permitted File permissions, no index file, a denyruleerror.log 404 Not Found: the address was not found Wrong root, missing file, non-matchinglocationerror.log, application 500 Internal Server Error Application error, redirect loop Application log 503 Service Unavailable: temporarily not available Rate or connection limit, maintenance mode error.log
: Enlarge
502 Bad Gateway
What does it mean? Nginx tried to forward the request to the backend but could not connect or did not receive a valid response.
Likely causes and their traces in the log:
- The backend is not running or has crashed: the log shows
connect() failed (111: Connection refused). - Wrong address, port or socket path:
proxy_passorfastcgi_passdoes not point to where the application actually listens. If the socket file does not exist, the log saysNo such file or directory. - No permission on the socket:
connect() to unix:… failed (13: Permission denied). The user Nginx runs as cannot access the socket file. On systems with SELinux enabled, the security policy may also block the connection. - The backend closed the connection without answering:
upstream prematurely closed connection. The application process may have crashed during the request, been restarted or hit its memory limit. - The response headers did not fit in the buffer:
upstream sent too big header. Very large cookies or headers cause this; theproxy_buffer_sizevalue is increased.
Fix: Start the service and find out from the application's log why it stopped. Make the address match the one the application listens on. A few seconds of 502 during a deployment or restart is normal; if it keeps recurring, the application is crashing. For PHP sites, see the guide on Nginx and PHP-FPM for details.
504 Gateway Timeout
What does it mean? Nginx connected to the backend and sent the request, but the response did not arrive within the expected time. The log says upstream timed out (110: Connection timed out).
Likely causes: a slow database query; an external service called by the application that does not respond; a long-running report, export or batch job; all application processes being busy because of load; if the backend is on another server, a firewall silently dropping the connection.
Diagnosis: Look at which addresses time out: a single page or the whole site? Try the backend directly and measure how long it takes. Adding the backend time to the access log makes it easier to find slow addresses:
# At http level: log format with request time and backend time
log_format timed '$remote_addr [$time_local] "$request" $status '
'request=$request_time upstream=$upstream_response_time '
'upstream_status=$upstream_status';
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/access.log timed;
location / {
proxy_pass http://127.0.0.1:3000;
}
}Fix: First remove the cause of the slowness (query, index, cache). Move tasks that naturally take long to the background and answer the user straight away. If it is really necessary, extend the time for the affected address only:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_connect_timeout 5s; # do not wait long if no connection can be made
proxy_read_timeout 60s; # default value
}
# Longer wait for the long-running report address only
location /reports/ {
proxy_pass http://127.0.0.1:3000;
proxy_read_timeout 180s;
}For proxied connections the time is set by proxy_read_timeout, for PHP-FPM by fastcgi_read_timeout; both default to 60 seconds. If the application's own time limit (such as max_execution_time in PHP) is shorter, review that too. If there is a CDN or a load balancing layer in front of Nginx, it has its own timeout; extending the time in Nginx does not affect that layer.
413 Request Entity Too Large
What does it mean? The request body sent by the client (usually an uploaded file) exceeds the permitted size. The limit is set by client_max_body_size; the default is 1m, that is 1 megabyte. The log says client intended to send too large body.
# Request body limit for the whole site (default 1m)
client_max_body_size 2m;
# Higher limit for the file upload address only
location /upload/ {
client_max_body_size 50m;
proxy_pass http://127.0.0.1:3000;
}Fix: Raise the limit to what you really need; the directive can be written at http, server or location level. Raising it for the upload address only is safer than raising it for the whole site. Match the application's own limits as well: if upload_max_filesize and post_max_size in PHP are smaller, the upload is rejected on the PHP side instead. For checking uploaded files, see the guide on file upload security.
499: the client closed the connection
What does it mean? 499 is not a standard HTTP code; it is specific to Nginx and appears only in the access log. The client closed the connection before Nginx could send the response; since nobody is left to receive a response, the visitor never sees this code.
Likely causes: the visitor closed or refreshed the page or moved to another one; the mobile app's or API client's own timeout is shorter than Nginx's; a CDN or load balancer in front of Nginx gave up waiting.
Diagnosis and fix: An occasional 499 is normal. If they cluster on a particular address, that address answers slowly: the real problem is speed, so follow the steps in the 504 section. Keep the timeout of the layer in front and the timeout in Nginx consistent with each other.
403 Forbidden
What does it mean? The server understood the request but refuses to fulfil it.
- File permissions: the log shows
(13: Permission denied). The user Nginx runs as must be able to read the file and must have traverse (x) permission on all parent folders leading to it. - No index file: the log shows
directory index of … is forbidden. A folder was requested, none of the files named in theindexdirective was found and directory listing is off. Check therootpath and theindexline. - Access rule: the log shows
access forbidden by rule. Adenyrule blocked the request; if the rule was written on purpose (e.g. for hidden files), this is the expected behaviour. - The application's decision: if there is no line in the log, the 403 may have been returned by the application (authorisation check) or by a security layer in front.
Do not solve a permission problem by granting "full access to everyone"; for correct ownership and least privilege, see the guide on server and hosting security.
404 Not Found
What does it mean? Nothing was found for the requested address.
- The file really does not exist, or
rootis wrong: the log showsopen() "…" failed (2: No such file or directory). The full path in that line shows where Nginx looked for the file; most configuration mistakes become obvious once you read that path. - The wrong
locationmatched: the request may be landing in a different block from the one you expect. - Single-entry-point applications: in applications where one file such as
index.phphandles every address, a missingtry_filesline means the home page opens but the other pages return 404. - Path mismatch behind the proxy: if the application returns the 404, there is no line in the Nginx error log. A trailing slash in
proxy_passchanges the path sent to the backend; the details are in the guide on reverse proxy setup.
500 and 503 in brief
500 Internal Server Error mostly comes from the application: an uncaught error, a broken configuration file or a database connection problem. The cause is in the application's or PHP's error log. Nginx itself rarely generates a 500; the typical example is an internal redirect loop, which appears in the log as rewrite or internal redirection cycle.
503 Service Unavailable reports that the service cannot be provided for the moment. By default Nginx returns this code when a rate limit (limit_req) or connection limit (limit_conn) is exceeded; the log says limiting requests or limiting connections. The response returned on purpose in maintenance mode is also 503. The application itself may return 503 under heavy load as well.
A sudden, widespread rise in 502, 503 and 504 can also be a sign of heavy bot traffic; see DDoS and bot attacks.
After a change
Test every change you make to the configuration first, then reload. If the test fails, Nginx prints the file and line number of the faulty line; as long as you do not reload, the site keeps running with the old settings.
# Test the configuration
sudo nginx -t
# If the test succeeds, reload
sudo systemctl reload nginxThe error page shown to visitors should not contain a version, a file path or error details; the details stay in the log. After the problem is solved, watch the logs for a few days: if the same line keeps appearing, the cause is still there.
Frequently asked questions
Is a 502 error on my site or on the visitor's computer?
It is on the server side. Nginx is running but cannot reach the application behind it or does not get a valid response from it. There is nothing the visitor can do; the cause is written in the error log on the server.
Is raising the timeout enough to fix 504?
Most of the time it postpones the symptom without removing the cause. If a response takes longer than 60 seconds, the visitor will not wait anyway. Find the source of the slowness first; extend the time only for specific addresses that naturally take long.
I see 499 in the access log. Should I worry?
A small number of 499s is normal; visitors close or refresh pages. If they cluster on a particular address, that address answers slowly and what really needs fixing is speed.
There is nothing in the error log but I still get an error. Why?
The code most probably comes from the application and Nginx merely passes it on; check the application's log. Also make sure you are looking at the right log file: a separate error_log may be defined for the site.
How can I tell whether Nginx or the application generated the error?
Error pages generated by Nginx are plain pages that say "nginx" at the bottom, and there is a matching line in the error log. The application's error page carries its own design and no line appears in the Nginx error log.
BYK Yazılım Support Team
This guide is written and regularly reviewed by the BYK Yazılım support team. Last updated: 4 October 2026.
Related guides
- How to set up Nginx as a reverse proxyStep-by-step setup: server block, proxy_pass, forwarded headers, WebSocket, timeouts and real client IP.
- Nginx and PHP-FPM: how PHP sites run on Nginxfastcgi_pass, SCRIPT_FILENAME, try_files, the pool concept, socket permissions and the 502 error.
- What is Nginx and what is it used for?The roles of Nginx, its event-driven architecture, how it differs from Apache, configuration blocks and basic commands.
- DDoS and bot attacksSigns, CDN and WAF, rate limiting, caching and working together with your hosting provider.
Let us talk about your website infrastructure
BYK Yazılım builds corporate websites. Write to us with any questions about your site.
Contact us Our corporate website service