The page is text on white, in the default browser font, and it has not changed in years: "Proxy Error", then "The proxy server received an invalid response from an upstream server.", then "The proxy server could not handle the request GET /some/path.", then a line beginning "Reason:", and a footer naming Apache and the site's hostname. People who see it search for the first two lines, and a large share of them then go looking for the proxy setting on their own computer, because the page said "proxy server" and they have heard the word before.
That search is a dead end, and saying so clearly is most of this article's value. The proxy in the message belongs to the website. It is Apache, the web server, running in a role called a reverse proxy: it receives your request and forwards it to another program, the "upstream server", which actually builds the page. When that program fails to answer properly, Apache has nothing to show you, so it shows you this. Your proxy settings, your VPN, and your browser had no part in it. A visitor with nothing configured sees the same page at the same moment.
Which proxy, and which server
Two proxies exist in this story, and only one of them is yours. A forward proxy is something you configure on your device so that your requests go out through it; that is what a proxy service sells and what the settings pages on your computer are about. A reverse proxy is something a website runs in front of itself, invisible to you, so that one public server can hand requests to whatever runs behind it. Apache's mod_proxy module is one of the most common reverse proxies on the web, and this page is its standard failure message. Our explainer on forward versus reverse proxies covers the distinction in depth.
Your browser
request arrives fine
Site's Apache (reverse proxy)
forwards to the backend
Backend application
no valid answer = Proxy Error
The request reached the site. Apache accepted it, which is why you got a page at all rather than a timeout. Apache then asked the backend, and the backend crashed, hung past the time limit, closed the connection, or answered with something that was not HTTP. Apache reports all of those as a 502 with a Reason line that says which.
What the Reason line means
| Reason line | What happened behind the site | Typical cause |
|---|---|---|
| Error reading from remote server | The backend accepted the request and then closed or went silent before a full response | A crash mid-request, a request longer than the proxy timeout, or a reused connection the backend had already dropped |
| DNS lookup failure for: hostname | Apache could not resolve the backend's name | A ProxyPass line pointing at a hostname that does not resolve on the Apache host |
| Error during SSL Handshake with remote server | Apache could not complete TLS with an HTTPS backend | A certificate the proxy does not trust, a hostname mismatch, or SSLProxyEngine not enabled |
"Error reading from remote server" is the one most people see, and it is the least specific: it says the backend stopped talking, not why. The why lives in the backend's own log, on the site's side.
If you are a visitor
The honest list is short.
- Wait a minute and reload. Backends restart, deploys roll, and single requests time out. A large share of these pages are gone on the second try.
- Try another page on the site. If the home page loads and one particular action fails (a search, a report, an export), that action takes longer than the site's backend timeout allows, and the site's operators need to know which one.
- Leave your own settings alone. Nothing about your proxy configuration, VPN, DNS, cache, or cookies is involved. If someone tells you to reset your proxy settings for this page, they have confused the two kinds of proxy.
- Tell the site, with the time and the URL, if the page persists beyond a few minutes. The footer line names the server and port, which confirms to them where it came from.
If you run the server
Here the page is a gift, because the Reason line and the error log narrow the cause quickly.
Confirm the backend is up and reachable from Apache. On the Apache host, request the backend directly at the address in your ProxyPass line, for example curl -v http://127.0.0.1:8080/some/path. A refused connection means the backend is not listening; a hang means it is listening but not answering; an answer here while Apache still fails points at the proxy configuration rather than the backend.
Read both logs for the same request. Apache's error log carries the Reason and the backend address; the backend's log carries the exception, the crash, or the slow query. "Error reading from remote server" with a backend log showing a worker killed on memory, or a request that took 90 seconds, is a complete diagnosis.
Align the timeouts. Apache gives up on the backend after ProxyTimeout (or the timeout= parameter on the ProxyPass line), which defaults to the server's Timeout. If the application is allowed to run longer than that, every slow request produces this page. Either raise the proxy timeout for the slow location, or lower the application's limit so it fails with its own error page before Apache gives up. For a genuinely slow endpoint, a dedicated <Location> with a longer timeout= is cleaner than raising it globally.
Handle backends that close idle connections. mod_proxy_http reuses connections to the backend. A backend that closes an idle connection without Apache noticing produces exactly "Error reading from remote server" on the next request through it. Two environment variables address this: SetEnv proxy-nokeepalive 1 disables connection reuse to the backend entirely, and SetEnv proxy-initial-not-pooled 1 avoids sending a client's first request over a pooled connection. Apache's own documentation describes both under mod_proxy_http. Setting disablereuse=on on the ProxyPass line is the per-backend version.
Fix HTTPS to the backend. Proxying to an https:// backend needs SSLProxyEngine On, and Apache verifies the backend's certificate by default. A self-signed backend certificate needs either a trusted CA path (SSLProxyCACertificateFile) or, for a backend on the same private network where you accept the risk, relaxed verification with SSLProxyVerify none and SSLProxyCheckPeerName off. The handshake Reason line is the tell.
Check that the backend speaks HTTP. Pointing ProxyPass at a port that runs something other than HTTP, for instance a raw application socket or a database, produces an "invalid response" because the bytes coming back are not an HTTP response at all.
Preserve the host if the backend routes by it. ProxyPreserveHost On passes the original Host header through, which some applications need to answer at all rather than returning an error Apache cannot interpret.
How this differs from the other gateway errors
Apache's Proxy Error page is a 502 with a Reason line. nginx reports the same class of failure as a bare "502 Bad Gateway". A 504 means the front server waited the full timeout and got nothing, rather than getting something broken; a 503 means a server answered that it cannot serve right now. Our guides to 502 Bad Gateway through a proxy, 504 Gateway Timeout, and 503 Service Unavailable cover those, including the case where the gateway in question is a forward proxy you configured yourself, which is the one situation where the visitor's own proxy is the cause and the fix is a different exit.
Who fixes what
The proxy server in this message is the website's own Apache, the upstream server is the program behind it, and the failure is between the two. Visitors reload and move on. Administrators read the Reason line, curl the backend from the Apache host, align the timeouts, and stop reusing connections to a backend that drops them.