How to Fix a 500 Internal Server Error
Two quick tests show who sent the 500, then three fixes for scripts, developers and site owners.
Updated
TL;DR
500 Internal Server Error means the server that answered hit an unexpected failure and could not finish your request; through a proxy, the website or the proxy itself may have sent it. Wait a minute and reload once; if it fails again, find out which side sent it.
What a 500 looks like in each client
Server pages often name their software; the client rows show whether the proxy or the site sent it.
| Where | What you see |
|---|---|
| Chrome (500 with an empty body) | This page isn't working. 127.0.0.1 is currently unable to handle this request. HTTP ERROR 500 |
| nginx (default 500 page, server_tokens off) | 500 Internal Server Error nginx |
| Apache httpd (default 500 page) | Internal Server Error The server encountered an internal error or misconfiguration and was unable to complete your request. |
| curl 8.7.1, proxy answered CONNECT with 500 | curl: (56) CONNECT tunnel failed, response 500 |
| curl --fail, site answered 500 | curl: (22) The requested URL returned error: 500 |
| Python urllib, proxy answered CONNECT with 500 | urllib.error.URLError: <urlopen error Tunnel connection failed: 500 Internal Server Error> |
| Python urllib, site answered 500 | urllib.error.HTTPError: HTTP Error 500: Internal Server Error |
Why this happens
The server's own code failed while handling your request, so it gave up.
Usually the site's app hit an exception it did not handle, often on input it never checked, or lost its database. MDN also lists bad configuration, memory exhaustion and file permissions.
Diagnose your 500 first
Tell proxy from site first, then a passing fault from one that repeats.
Load the https:// page in Chrome through the same proxy; a 500 page came from the site's side, ERR_TUNNEL_CONNECTION_FAILED from the proxy.
Run curl with -w '%{http_connect} %{http_code}' through the proxy to an https:// URL; 500 000 means the proxy sent it, 200 500 the site.
For an http:// URL no tunnel forms, so compare the 500's Server header with and without the proxy; a match means the site sent it.
Send the same request three times a minute apart; if all three fail while other pages load, something in that request triggers it.
If your site uses Cloudflare, search the 500's HTML for cloudflare or cloudflare-nginx; if present, it is Cloudflare's to fix, not your host's.
Solutions ranked by effectiveness
Start with a retry; move on when one request keeps failing.
- Most common fix
Retry safe requests after a pause
For scripts whose 500s come and go: resend GET and other safe requests with growing pauses. curl's --retry skips a proxy's 500 on CONNECT unless you add --retry-all-errors.
curl -sS -o page.html -w '%{http_code}\n' \ --retry 3 --retry-all-errors --retry-max-time 120 \ -x http://USERNAME:PASSWORD@proxy.geonode.io:9000 \ https://example.com/ - For developers
Shrink the request until the 500 stops
For one request that fails every time while the rest of the site works.
In Chrome DevTools, right-click the failing request and choose Copy > Copy as cURL.
Delete one header, cookie or body field at a time and resend the command.
When the 500 stops, the part you removed last holds the value the server mishandles.
Send the site owner that smallest failing request and its time, minus cookies and passwords.
- Site owners
Read the error log at that second
For a 500 from your own server. The error log, or your app's own log, names the exception or config line behind it.
Match the failing request's timestamp to entries written in the same second.
If it names an .htaccess directive, fix its spelling or allow it with AllowOverride.
If pages show Error establishing database connection, check the database server or ask your host.
Stop the 500 from coming back
Two habits for scripts that use a proxy, then three for whoever runs the server.
Before resending a failed POST, check whether the first try took effect, such as a placed order.
For each 500, log the UTC time, target URL and proxy port; Geonode's docs ask for request details.
Answer malformed input with 400 before it reaches code that can throw, so it never ends as a 500.
Print a request ID on every 500 page and log the same ID with the error.
Run Express with NODE_ENV=production, so its built-in error handler keeps the stack trace out of 500 pages.
Related errors
Learn more
FAQ
Reproduce a 500 by country
When users in one country report 500s, load your site through a residential IP there.


