TIme in Dallas: |
500, 502, 503, 504 Errors Explained
Text size: A+ A-

500, 502, 503, 504 Errors Explained

Click to rate this post!
[Total: 1 Average: 5]

When a site throws a “500 Internal Server Error” or a “502 Bad Gateway” instead of the page you expected, it is stressful for everyone involved — especially the person building or maintaining the site. The frustrating part about 5xx errors is that they tell you the problem is on the server, but they almost never tell you exactly what broke.

In this article, we will break down the five most common 500-series codes — 500, 501, 502, 503, and 504. We will look at where they usually come from, how to diagnose them, and, most important, how to get the site working again.

What do all these 500, 502, 503 codes actually mean?

In short: if you see a 5xx error, the problem is not on your computer or in your browser. It is on the server where the site is hosted.

HTTP uses status codes so the server can tell the browser how the request went. Code 200 means everything is fine and the page loaded. 404 means the page was not found. Every code that starts with a five is basically an SOS signal: “Something broke on the server, and I cannot complete your request.” The details are often hidden, but the very fact that it is a 5xx error tells you to look on the server side.

Here is a quick guide to the main 500-series errors:

  • 500 (Internal Server Error). The all-purpose one. The server hit an unexpected condition and does not know how to respond. It can mean almost anything, from a bug in the site code to a server misconfiguration. It is the most common and one of the trickiest errors because the cause is not obvious.
  • 501 (Not Implemented). “I do not support that.” The server does not understand or support the method you requested. For example, if your site sends a PATCH request and the server does not know how to handle it, it may return 501. In practice, this is not seen very often.
  • 502 (Bad Gateway). “I am just the middleman, and the server I asked gave me nonsense.” This happens when one server, such as Nginx acting as a gateway, cannot get a valid response from another server, such as PHP-FPM or Apache. Classic for stacked or layered systems.
  • 503 (Service Unavailable). “Sorry, I am busy or under maintenance, try again later.” The server temporarily cannot handle the request because of overload or planned work. This is the only 5xx error where the user may see a Retry-After header telling them when to try again.
  • 504 (Gateway Timeout). “I am the middleman, and the server I was waiting on took too long to respond.” This is similar to 502, but in this case the gateway simply did not get a response from the upstream server within the allowed time.

The biggest danger with these errors is not only that users cannot see the site. Search engines see them too.

If Google or Yahoo bots keep running into 500-level errors during indexing, they may lower the site’s rankings or reduce how often they come back. So fixing these errors is not only a technical task — it is an SEO task too.

500 Internal Server Error: the biggest headache

This error is like a black box. The message itself tells you almost nothing, so diagnosing a 500 always starts with the logs.

Where it comes from:

  1. Errors in site scripts. The most common cause. An unhandled exception in code, a syntax error, a call to a nonexistent function. If the site runs on PHP, 500 is a frequent visitor when fatal errors happen.
  2. Problems with the .htaccess file (for Apache). One bad directive or a typo in this file can take down the whole site. A classic example is a broken mod_rewrite rule. This is also a common source of 500 errors.
  3. Wrong file permissions. Script files should usually be set to 644 and folders to 755. If permissions are wrong, the web server may not be able to read or execute the file it needs.
  4. Resource limits exceeded. Too many requests, not enough memory for the script, or a max_execution_time limit being hit can all lead to a 500.
  5. Database connection problems. If your code tries to query the database but the DB server does not respond or returns an error, the PHP script may fail with a 500.

How to diagnose and fix it:

  • Check the logs. This is the first and most important rule. Web server logs, whether Nginx or Apache, and PHP logs are your best friends. That is where you will usually find the exact cause.
  • Check .htaccess. If you are on Apache, temporarily rename the file and see whether the error disappears. If it does, the problem is in that file. Then comment out lines one by one until you find the broken directive.
  • Turn on error display. For debugging only, you can temporarily show errors in the script itself so they appear on screen. Important: never leave that enabled on a live site, because it can expose sensitive information.
  • Check file permissions. Make sure files and folders have the correct permissions.
  • Check PHP limits. Increase memory_limit and max_execution_time in PHP settings, for example through .htaccess or php.ini, if the error happens on heavy scripts.

502 Bad Gateway: a communication failure

Imagine you call a receptionist and ask to be connected to the boss. The receptionist dials the number, but instead of the boss’s voice, she hears strange noise on the line. She does not know what to do with that, so she tells you, “Bad gateway.” That is a 502.

Where it comes from:

  1. The backend server is down. For example, Nginx cannot connect to PHP-FPM because PHP-FPM is stopped.
  2. PHP-FPM is overloaded. Too many incoming requests, and the process cannot keep up, so it returns an error to Nginx or does not respond at all.
  3. Proxy configuration problems. The upstream is set wrong, or timeout settings are misconfigured.
  4. Headers are too large. If your backend sends very large headers and Nginx is only configured to accept smaller ones, a 502 can appear.

How to diagnose and fix it:

  • Check whether the services are running. Make sure the backend, such as PHP-FPM, Apache, or Gunicorn, is active and listening on the correct port or socket.
  • Check backend logs. PHP-FPM or Apache logs often show the exact reason for the failure.
  • Check timeout settings. In Nginx config, settings like proxy_read_timeout and fastcgi_read_timeout can be increased so the backend has more time to respond. This helps if scripts take a long time.
  • Check buffer settings. Increase header and response buffer sizes such as proxy_buffer_size and fastcgi_buffer_size.

503 Service Unavailable: the server is at its limit

This error is blunt: “I would love to serve you, but I cannot right now.” That is not always a problem — sometimes it is normal.

Where it comes from:

  1. Server overload. The number of simultaneous requests has exceeded the server’s capacity, whether that means RAM, CPU cores, or both.
  2. Hosting limits reached. On shared hosting, each user has resource quotas. If your site exceeds them, the host may start returning 503 errors.
  3. Planned maintenance. An admin may intentionally put the site into maintenance mode.
  4. A DDoS attack or sudden traffic spike. That is also a form of overload.

How to diagnose and fix it:

  • Find out whether it is temporary. If the error appears briefly and goes away, it may simply be a traffic spike.
  • Check server load. If you have access, look at CPU load, memory usage, and disk activity.
  • Optimize code. Heavy scripts and inefficient database queries all add load.
  • Enable caching. Proper caching can reduce server load dramatically.
  • Consider upgrading hosting. If the project has outgrown its current plan, it may be time for a VPS or a dedicated server.

504 Gateway Timeout: the wait went too long

502 and 504 are close relatives. With a 502, the gateway got a bad response. With a 504, it got no response at all before the timeout expired.

Where it comes from:

  1. A long-running script. A PHP script takes one or two minutes to finish, while Nginx waits only 60 seconds by default. The timeout hits, and the user sees a 504.
  2. Slow database queries. A complex SELECT query that takes several seconds can trigger a timeout if the backend and Nginx are not configured correctly.
  3. A hung backend. PHP-FPM is frozen and not answering Nginx requests.

How to diagnose and fix it:

  • Increase timeouts. In Nginx config, raise proxy_read_timeout and fastcgi_read_timeout. That gives long-running scripts time to finish.
  • Optimize queries. Find and speed up the slow parts of the app. That helps both the errors and overall performance.
  • Check backend logs. If scripts are hanging, the logs may point to the exact cause.

What to do if nothing helped: action plan

Start with the logs. Always. Web server and application logs are your map.

Reproduce the problem. Try triggering the error again, for example with curl from the command line. That shows the exact status code and response headers.

Check whether you recently changed anything. Did you update the site engine? Change server settings? Very often the problem is the last change you made.

Disable anything unnecessary. Temporarily deactivate plugins, rename .htaccess, switch to the default theme. If the error disappears, you found the culprit.

Contact hosting support. If you do not have server access or you have tried everything, your hosting provider’s support team should help, especially if the issue is on their side.

Quick diagnostic checklist:

  • 500 Internal Server Error: check logs, file permissions, .htaccess, and script code.
  • 502 Bad Gateway: check whether backend services like PHP-FPM are running, plus backend logs and proxy settings.
  • 503 Service Unavailable: check server load, hosting limits, and whether there is a DDoS attack or maintenance.
  • 504 Gateway Timeout: increase Nginx timeouts, optimize slow queries and scripts.

Any 5xx error is more than an annoyance. It is a signal that something is wrong in the server infrastructure or in the code. Keep track of these errors regularly, for example through Google Search Console, analyze the causes, and fix them. That will make your site more reliable and help protect its search rankings.

Errors in .htaccess That Lead to 5xx

Below are three common examples from my own experience that cause a site to return 500, 502, or 503 errors.

An endless redirect loop (500 Internal Server Error):

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.poznayu.com [NC]
RewriteRule ^(.)$ https://poznayu.com/$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^poznayu.com [NC]
RewriteRule ^(.)$ https://www.poznayu.com/$1 [R=301,L]

The rules loop back on each other: the first rule removes www., and the second adds it back. Apache tries to process an endless chain and, at a certain point, stops execution and returns a 500 error. This kind of loop is easy to create if you do not notice a conflict between the conditions.

An incorrect php_value or php_flag directive (500):

php_value upload_max_filesize 2M
php_flag display_errors on

These directives only work when mod_php is enabled. If the server is running through PHP-FPM or FastCGI, Apache cannot process them and fails with a 500 error. The same thing happens if you specify a nonexistent parameter or make a syntax mistake, such as missing a quote.

Invalid RewriteRule syntax (500):

RewriteEngine On
RewriteRule ^article/([0-9]+)/?$ article.php?id=$1 [NC,L,FLAG]

Using the nonexistent FLAG flag is a typo. Apache does not understand that instruction and stops processing the file with an error. The same thing can happen with an extra comma, an unclosed square bracket, or an unescaped character in a regular expression.

PHP errors when sending headers

PHP errors rarely cause 5xx errors directly, but under certain conditions they absolutely can. Here are five typical examples from my own practice.

Trying to send a header after output has already been sent (500 or blank page):

echo "Hello, user!";
header("Location: https://poznayu.com/new-page/");

Headers must be sent before any output reaches the browser. PHP does buffer output, but if buffering is disabled, or if output has already been sent, calling header() after echo triggers a “Cannot modify header information” error. Depending on the server settings, this can lead to a 500 Internal Server Error or simply cause the page to stop loading.

An endless redirect caused by bad logic in header():

if (strpos($_SERVER['REQUEST_URI'], 'step2') === false) {
header("Location: " . $_SERVER['REQUEST_URI'] . "?step2");
exit;
}

The code builds a new URL by adding a parameter, but if the check does not account for the parameter already being there, the script can keep redirecting over and over. A server-side redirect loop quickly hits the limit, for example RedirectLimit in Apache, and ends with a 500 or 502 error. The user sees “Too many redirects” or a server error.

Trying to set a header that is too large or has invalid syntax:

header("Set-Cookie: session=value; Max-Age=1000000000000000000000000000000");

The header value, such as the cookie lifetime, goes beyond valid limits. The web server or PHP cannot build the response correctly and the script ends with a fatal error. Or, if the header contains invalid characters, such as a newline inside the value, the server may return a 500. In an Nginx + PHP-FPM setup, this kind of error often turns into a 502 Bad Gateway, because fastcgi cannot read the response from PHP.

A database connection error without exception handling (500):

$pdo = new PDO('mysql:host=localhost;dbname=wrong_db', 'user', 'pass');
$pdo->query('SELECT * FROM users');

If PDO cannot connect because the database name is wrong, the password is incorrect, or MySQL is unavailable, it throws a PDOException. With default PHP settings, that exception is not caught, turns into a fatal error, and causes a 500 Internal Server Error. The logs will show “Uncaught PDOException.” This is especially common on sites where connection settings are stored in a config file and that file has been damaged or overwritten by accident.

Endless recursion in a function (500):

function factorial($n) {
return $n * factorial($n - 1);
}
echo factorial(10);

The function is missing a stopping condition (if ($n <= 1) return 1;). It keeps calling itself until PHP reaches the recursion depth limit, which is 256 by default. After that, the script fails with a fatal “Maximum function nesting level reached” error. The web server returns a 500 Internal Server Error. PHP error logs will show this message clearly. This kind of bug often appears after a refactor, when a developer accidentally removes the recursive base case.

Click to rate this post!
[Total: 1 Average: 5]
Ethan Carter

I’m Ethan Carter, an American developer and technical writer with more than 20 years of experience in systems and application programming. My core specialty is low-level development in Assembler: 22 years of hands-on work, including deep experience in code optimization, CPU architecture, and performance-critical solutions. I also hold a PhD in Assembler and have spent more than 18 years working with ASP.NET, building enterprise web systems, APIs, and scalable backend solutions.

In addition, I have 9 years of experience in C++ and C#, along with 7 years of hands-on microcontroller programming in Assembler. Thanks to this mix of academic background and practical engineering experience, I can write about software architecture, low-level optimization, and modern development in a way that makes complex technical topics clear for a professional audience.

Leave a Comment

Your email address will not be published. Required fields are marked *

Contact Us

Scroll to Top