Skip to main content

HTTP error codes and what to do about them

What every 4xx and 5xx you will actually meet means, and how to fix each one.

The status code narrows the problem to a layer. Here are the ones you will actually meet.

4xx — the request is the problem

CodeMeaningUsual cause / fix
400Bad RequestMalformed request; often a proxy or client bug
401UnauthorisedMissing/invalid credentials — check auth headers or login
403ForbiddenAuthenticated but not allowed — permissions, file mode, or a WAF rule
404Not FoundWrong URL, missing file, or a broken rewrite rule
405Method Not AllowedUsing GET where POST is needed (or vice versa)
408Request TimeoutClient too slow; or a too-aggressive timeout
429Too Many RequestsRate limit hit — back off, or for visitors, raise the limit
499Client Closed RequestThe client gave up (nginx-specific); often a symptom of slowness

403 after a migration is almost always file permissions — the web server user cannot read the files.

5xx — the server is the problem

CodeMeaningUsual cause / fix
500Internal Server ErrorAn unhandled exception — read the app log first
502Bad GatewayThe app behind the proxy is down or not listening where expected
503Service UnavailableOverloaded or in maintenance; check resources and load
504Gateway TimeoutThe app took too long to respond — slow query, deadlock, or overload

500 with an empty body is nearly always a fatal error before output — check the error log, which names the file and line.

502 means the proxy is fine but the thing it forwards to is not. Confirm the app is running and on the right port, then read its log.

504 usually means a slow backend: a missing index, an external call without a timeout, or genuine overload.

Working the problem

  1. Find the code in the access/error log.

  2. Match it to the layer above.

  3. Read the application log for 5xx; read the request for 4xx.

  4. Change one thing, retest.

Related reading