# erroneo.us — full text
> Every live page on https://erroneo.us as Markdown, generated 2026-10-22. Canonical URLs are given for each page; please cite them. Index: https://erroneo.us/llms.txt
---
title: "erroneo.us"
url: https://erroneo.us/
description: "A researched reference to common errors: confused words, grammar mistakes, HTTP status codes, JavaScript and Python errors, cognitive biases and popular myths."
type: home
section: "erroneo.us"
date_modified: 2026-10-22
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# erroneo.us
> A researched, source-linked reference to the mistakes people make most often — in writing, in code, in reasoning, and in what “everybody knows.” Each page shows the wrong version, the right version, and the evidence.
Latest in security · Thursday, October 22, 2026
[Security Digest](https://erroneo.us/security/) · [RSS](https://erroneo.us/security/feed.xml) · [JSON](https://erroneo.us/api/security/today.json)
Act now Oct 21, 2026 · CVE-2026-109618, CVE-2026-109619 · Exploited in the wild
## [PHP2Shell: Critical Unauthenticated RCE in PHP](https://erroneo.us/security/briefs/php2shell-php-rce/)
If PHP answers HTTP requests anywhere you run it, patch or apply a vendor fix today; this is pre-application, unauthenticated, and attack traffic started before the patch shipped.
**Must act:** Anyone running PHP behind a web server (mod_php, PHP-FPM, php-cgi, FrankenPHP, LiteSpeed), including WordPress, Drupal, Magento, Laravel and appliance or container images that bundle PHP.
**Can relax:** Hosts where PHP is only used from the command line (scripts, cron, Composer) and never handles untrusted HTTP requests, and RHEL 7 or older, which Red Hat says ships unaffected PHP.
First steps
1. Inventory every PHP that serves HTTP: servers, containers, appliances, shared hosting.
2. Upgrade to 8.5.12, 8.4.27, 8.3.36 or 8.2.35, or install your distribution's fixed package, then restart every PHP worker (php-fpm, Apache).
3. Rebuild and redeploy container images from refreshed php:* or distro base images; do not just restart old containers.
[Full brief & sources →](https://erroneo.us/security/briefs/php2shell-php-rce/)
Patch this week Oct 21, 2026 · CVE-2026-111497, CVE-2026-105482 · No known exploitation
## [Node.js October 2026 Security Releases: 10 CVEs Fixed](https://erroneo.us/security/briefs/nodejs-october-2026-security-releases/)
Four high-severity fixes, including a Brotli decoder memory-corruption bug the project says permits remote code execution, make this a routine-but-real upgrade: roll every supported line forward this week.
**Must act:** Anyone running Node.js 22.x, 24.x or 26.x in production, especially services that decompress untrusted Brotli data or make TLS connections to hosts given as IP addresses.
**Can relax:** Nobody needs to drop everything today: no exploitation is reported, and the low-severity Permission Model and ZIP fixes only matter if you use those features.
First steps
1. Check every runtime that serves traffic: node -v in each container, VM and CI image.
2. Upgrade to 26.12.1, 24.22.1 or 22.23.4 (nvm install 24.22.1, or your package manager / official node:* images), then restart processes.
3. Rebuild and redeploy container images and single executable applications (SEAs) so they embed the fixed runtime.
[Full brief & sources →](https://erroneo.us/security/briefs/nodejs-october-2026-security-releases/)
[**0** new known-exploited (KEV) · **3** critical advisories on Oct 21, 2026 — open the digest →](https://erroneo.us/security/2026-10-21/)
Error of the Day · Thursday, October 22, 2026
## Today’s error: [CORS errors: the server answered, the browser said no](https://erroneo.us/daily/cors-error/)
The most misdiagnosed error in web development is not a server crash. It is a browser enforcing a permission slip your server never signed.
From the [Developers](https://erroneo.us/developers/) desk · [All errors of the day](https://erroneo.us/daily/) · [RSS](https://erroneo.us/feed.xml)
[Read today’s error →](https://erroneo.us/daily/cors-error/)
Earlier this week
1. Oct 21 Language[Comprised of: the phrase editors keep circling](https://erroneo.us/daily/comprised-of/) 'Is comprised of' is common but many editors still flag it. The whole comprises the parts; the parts compose the whole. Use 'comprises' or 'consists of'.
## Play with your errors
Five interactive tools, built on the same cited guides. Free, no sign-up, nothing leaves your browser.
- [Spot the Error Timed rounds of sentences with one mistake. Tap the wrong word before the red pen does.](https://erroneo.us/spot-the-error/)
- [HTTP Status Code Explorer Every registered code, searchable by number, class or keyword, with what to do next.](https://erroneo.us/developers/http-status-codes/#status-code-explorer)
- [Bias or Fallacy? Everyday scenarios. Name the cognitive bias or logical fallacy hiding inside.](https://erroneo.us/bias-or-fallacy-quiz/)
- [Error Message Decoder Paste a JavaScript or Python error. Get the plain-English meaning and the fix.](https://erroneo.us/error-decoder/)
- [Myth or Fact? Swipe through popular claims. Every verdict is backed by a cited source.](https://erroneo.us/myths/#myth-or-fact)
## The guides
Four clusters, 21 guides, every claim linked to a source.
### [Language](https://erroneo.us/language/)
Confused words, grammar slips, misspellings, mispronunciations and mangled idioms.
- [Commonly confused words](https://erroneo.us/language/commonly-confused-words/)
- [Common grammar mistakes](https://erroneo.us/language/common-grammar-mistakes/)
- [Commonly misspelled words](https://erroneo.us/language/commonly-misspelled-words/)
- [Commonly mispronounced words](https://erroneo.us/language/commonly-mispronounced-words/)
- [Misused idioms and phrases](https://erroneo.us/language/misused-idioms-and-phrases/)
[All language guides →](https://erroneo.us/language/)
### [Developers](https://erroneo.us/developers/)
HTTP status codes, JavaScript and Python errors decoded, and the bugs that made history.
- [HTTP status codes, explained properly](https://erroneo.us/developers/http-status-codes/)
- [401 Unauthorized vs 403 Forbidden](https://erroneo.us/developers/http-401-vs-403/)
- [404 Not Found](https://erroneo.us/developers/http-404-not-found/)
- [429 Too Many Requests](https://erroneo.us/developers/http-429-too-many-requests/)
- [500 Internal Server Error](https://erroneo.us/developers/http-500-internal-server-error/)
- [502 Bad Gateway vs 504 Gateway Timeout (and 503)](https://erroneo.us/developers/http-502-vs-504/)
- [418 I'm a teapot](https://erroneo.us/developers/http-418-im-a-teapot/)
- [Common JavaScript errors, explained](https://erroneo.us/developers/javascript-errors/)
- [Common Python errors, explained](https://erroneo.us/developers/python-errors/)
- [Famous software bugs in history](https://erroneo.us/developers/famous-software-bugs/)
[All developers guides →](https://erroneo.us/developers/)
### [Thinking](https://erroneo.us/thinking/)
Cognitive biases and logical fallacies: the errors we make before we say a word.
- [Cognitive biases: the predictable ways good minds go wrong](https://erroneo.us/thinking/cognitive-biases/)
- [Logical fallacies: how arguments break, with examples](https://erroneo.us/thinking/logical-fallacies/)
[All thinking guides →](https://erroneo.us/thinking/)
### [Myths](https://erroneo.us/myths/)
Science, history, nutrition and money misconceptions, checked against primary sources.
- [Science myths that refuse to die](https://erroneo.us/myths/science-myths/)
- [History myths: what really happened](https://erroneo.us/myths/history-myths/)
- [Nutrition myths: what the evidence actually says](https://erroneo.us/myths/nutrition-myths/)
- [Money mistakes and personal-finance myths](https://erroneo.us/myths/money-mistakes/)
[All myths guides →](https://erroneo.us/myths/)
## Most looked-up
- [Language Commonly confused words Affect or effect? Then or than? A skimmable table of 45 commonly confused English words with meanings, examples and memory tricks that actually stick.](https://erroneo.us/language/commonly-confused-words/)
- [Developers HTTP status codes, explained properly Every HTTP status code from 100 to 511 in plain English: what each means per RFC 9110, the usual cause, and the common mistakes with 401, 404, 429 and 5xx.](https://erroneo.us/developers/http-status-codes/)
- [Developers Common JavaScript errors, explained What "Cannot read properties of undefined", "x is not a function", CORS and JSON.parse errors mean, with exact browser messages and fixes.](https://erroneo.us/developers/javascript-errors/)
- [Thinking Cognitive biases: the predictable ways good minds go wrong A sourced guide to 20 common cognitive biases: anchoring, confirmation bias, sunk cost, Dunning-Kruger and more, with examples, fixes and replication caveats.](https://erroneo.us/thinking/cognitive-biases/)
- [Myths Nutrition myths: what the evidence actually says Eggs and cholesterol, MSG, detoxes, eight glasses of water, the five-second rule, best-by dates: 13 food myths, checked against FDA, USDA and research.](https://erroneo.us/myths/nutrition-myths/)
- [Developers Famous software bugs in history Ariane 5, Mars Climate Orbiter, Therac-25, Knight Capital, the Patriot clock, Y2K and CrowdStrike: what went wrong, per official reports, and the lessons.](https://erroneo.us/developers/famous-software-bugs/)
## What this site is
**erroneo.us** (say it “erroneous”) is a field guide to being wrong in predictable ways. Some errors are small and social, like writing *effect* when you meant *affect*. Some are expensive, like a unit mismatch that sends a spacecraft too deep into a planet’s atmosphere. Most sit in between: a confusing `502` on a Friday deploy, a `TypeError` that only appears in production, a nutrition rule you absorbed as a child and never checked.
The common thread is that these mistakes are *patterned*. People confuse the same word pairs, hit the same stack traces and repeat the same myths. That makes them worth documenting once, carefully, with the fix next to the failure.
## How the pages work
- **Wrong next to right.** Red strikethrough for the error, green underline for the correction, and a sentence on *why*.
- **Sources on every claim.** Specifications like RFC 9110 for HTTP, official language docs, investigation reports for historical software failures, and government or peer-reviewed sources for health and money. See [sources & methodology](https://erroneo.us/sources/).
- **Skimmable first, thorough second.** Tables and quick answers up top, the nuance underneath, and an FAQ at the end.
- **Corrections welcome.** A site named after errors has to be strict about its own. Our [corrections policy](https://erroneo.us/about/#corrections) explains how we fix them.
## Start here
Writers and students usually want [commonly confused words](https://erroneo.us/language/commonly-confused-words/) or [common grammar mistakes](https://erroneo.us/language/common-grammar-mistakes/). Developers land on the [HTTP status code reference](https://erroneo.us/developers/http-status-codes/), [JavaScript errors](https://erroneo.us/developers/javascript-errors/) and [Python errors](https://erroneo.us/developers/python-errors/). If you want to argue better, read [logical fallacies](https://erroneo.us/thinking/logical-fallacies/) and [cognitive biases](https://erroneo.us/thinking/cognitive-biases/). And if you suspect something you were taught is wrong, the [myths section](https://erroneo.us/myths/) is for you.
---
Source page: https://erroneo.us/ · More: https://erroneo.us/llms.txt
==========
---
title: "Developer errors"
url: https://erroneo.us/developers/
description: "Plain-English references for HTTP status codes, common JavaScript and Python error messages, and the famous software bugs that changed engineering."
type: section
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# Developer errors
> Error messages decoded: what the spec actually says, what usually causes it, and how to fix it fast.
- [Developers HTTP status codes, explained properly Every HTTP status code from 100 to 511 in plain English: what each means per RFC 9110, the usual cause, and the common mistakes with 401, 404, 429 and 5xx.](https://erroneo.us/developers/http-status-codes/)
- [Developers 401 Unauthorized vs 403 Forbidden 401 means authenticate and try again; 403 means credentials will not help. The RFC 9110 rules, OAuth bearer-token cases, and when 404 is the safer answer.](https://erroneo.us/developers/http-401-vs-403/)
- [Developers 404 Not Found What HTTP 404 Not Found really means under RFC 9110, how it differs from 410 Gone, why soft 404s hurt SEO, and how to find and fix broken URLs on your site.](https://erroneo.us/developers/http-404-not-found/)
- [Developers 429 Too Many Requests HTTP 429 means you hit a rate limit. What RFC 6585 says, how to honor Retry-After, exponential backoff with jitter in code, and the new RateLimit headers draft.](https://erroneo.us/developers/http-429-too-many-requests/)
- [Developers 500 Internal Server Error HTTP 500 means the server hit an unexpected condition. How to find the real cause in logs, the usual culprits, and why stack traces must never reach users.](https://erroneo.us/developers/http-500-internal-server-error/)
- [Developers 502 Bad Gateway vs 504 Gateway Timeout (and 503) 502, 503 and 504 all mean something behind the proxy failed. How to tell them apart, read nginx, Caddy and load balancer logs, and fix the usual causes.](https://erroneo.us/developers/http-502-vs-504/)
- [Developers 418 I'm a teapot The April Fools' status code that the HTTP spec now has to reserve forever.](https://erroneo.us/developers/http-418-im-a-teapot/)
- [Developers Common JavaScript errors, explained What "Cannot read properties of undefined", "x is not a function", CORS and JSON.parse errors mean, with exact browser messages and fixes.](https://erroneo.us/developers/javascript-errors/)
- [Developers Common Python errors, explained IndentationError, NameError, 'NoneType' object is not subscriptable, KeyError, ModuleNotFoundError and more: what each Python error means and how to fix it.](https://erroneo.us/developers/python-errors/)
- [Developers Famous software bugs in history Ariane 5, Mars Climate Orbiter, Therac-25, Knight Capital, the Patriot clock, Y2K and CrowdStrike: what went wrong, per official reports, and the lessons.](https://erroneo.us/developers/famous-software-bugs/)
## Read the error, then read the spec
An error message is the most honest thing a computer will tell you all day, but it is written for the machine’s convenience, not yours. `Cannot read properties of undefined` tells you *where* something was missing, not *why*. A `502 Bad Gateway` tells you that a proxy got a bad response, but not which upstream failed. This section translates the common ones.
For HTTP we work from the current standard, [RFC 9110 (HTTP Semantics)](https://www.rfc-editor.org/rfc/rfc9110), plus the RFCs that add codes like `429`. For language errors we use the official references: [MDN’s JavaScript error reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors) and the [Python built-in exceptions documentation](https://docs.python.org/3/library/exceptions.html).
## A quick triage order
| You see | Start with |
|---|---|
| `4xx` status | The request: URL, method, auth headers, body. See [the status code reference](https://erroneo.us/developers/http-status-codes/). |
| `5xx` status | The server and anything in front of it: app logs, proxy logs, upstream health. See [500](https://erroneo.us/developers/http-500-internal-server-error/) and [502 vs 504](https://erroneo.us/developers/http-502-vs-504/). |
| JavaScript `TypeError` | The value on the left of the dot or the call. See [JavaScript errors](https://erroneo.us/developers/javascript-errors/). |
| Python traceback | The *last* line first, then the frame just above it. See [Python errors](https://erroneo.us/developers/python-errors/). |
And when you want perspective on why all of this matters, read [famous software bugs](https://erroneo.us/developers/famous-software-bugs/): overflow, unit and race-condition errors that cost rockets, lives and fortunes, each traced to its official investigation.
---
Source page: https://erroneo.us/developers/ · More: https://erroneo.us/llms.txt
==========
---
title: "Language errors"
url: https://erroneo.us/language/
description: "Guides to the English mistakes people search for most: commonly confused words, grammar errors, misspellings, mispronunciations and misused idioms."
type: section
section: "Language"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# Language errors
> The words, spellings and phrases that trip up careful writers — with memory tricks that actually stick.
- [Language Commonly confused words Affect or effect? Then or than? A skimmable table of 45 commonly confused English words with meanings, examples and memory tricks that actually stick.](https://erroneo.us/language/commonly-confused-words/)
- [Language Common grammar mistakes The grammar mistakes that actually cost you credibility, from comma splices to 'between you and I', plus the fake rules you can safely ignore. With fixes.](https://erroneo.us/language/common-grammar-mistakes/)
- [Language Commonly misspelled words Separate, definitely, accommodate, embarrass: a table of 50 commonly misspelled English words with the usual wrong spelling, why it happens and a memory trick.](https://erroneo.us/language/commonly-misspelled-words/)
- [Language Commonly mispronounced words Nuclear, espresso, February, often, GIF: which pronunciations dictionaries call nonstandard, which are fine, and the linguistics behind each one.](https://erroneo.us/language/commonly-mispronounced-words/)
- [Language Misused idioms and phrases For all intents and purposes, couldn't care less, begs the question, irregardless, literally: the real forms, their origins and what dictionaries say.](https://erroneo.us/language/misused-idioms-and-phrases/)
## Why the same mistakes keep happening
Most language errors are not about intelligence or education. They come from English itself: words that sound identical but are spelled differently (*their*, *there*, *they’re*), spellings borrowed from several languages at once, and fixed phrases that people learn by ear before they ever see them written. When a phrase is heard as “for all intensive purposes,” nothing in conversation corrects it. The error only shows up on the page.
Spellcheckers help with outright misspellings, but they are much weaker at catching a real word in the wrong place. *Loose* and *lose* are both correctly spelled, so a typo that swaps them sails through. That is why the guides in this section focus on **pairs, patterns and context**, not just lists.
## How to use this section
- **Proofreading something now?** Use the big table in [commonly confused words](https://erroneo.us/language/commonly-confused-words/) and search the page for the word you are unsure about.
- **Fixing a habit?** Each guide includes a memory trick. Pick the three errors you make most and learn only those.
- **Prescriptive vs. descriptive:** where dictionaries and style guides disagree (think *literally* or *irregardless*), we say so and link the sources, rather than pretending there is one rule.
Typos are a motor skill as much as a knowledge problem. If your errors come from fast fingers rather than uncertain spelling, deliberate practice helps: the free [typing trainer from allthingsN](https://allthingsn.com/typing/) has graded lessons for accuracy before speed.
---
Source page: https://erroneo.us/language/ · More: https://erroneo.us/llms.txt
==========
---
title: "Myths & misconceptions"
url: https://erroneo.us/myths/
description: "Popular myths about science, history, nutrition and money checked against primary sources: NASA, the FDA, the USDA, the CFPB and peer-reviewed research."
type: section
section: "Myths"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# Myths & misconceptions
> Things “everybody knows” that the evidence doesn’t support — each one traced back to a primary source.
- [Myths Science myths that refuse to die Do we use 10% of our brains? Is the Great Wall visible from space? Is glass a liquid? 13 common science myths, the real answers, and the studies behind them.](https://erroneo.us/myths/science-myths/)
- [Myths History myths: what really happened Was Napoleon short? Did Vikings wear horned helmets? Did Marie Antoinette say 'let them eat cake'? 11 popular history myths and what the record shows.](https://erroneo.us/myths/history-myths/)
- [Myths Nutrition myths: what the evidence actually says Eggs and cholesterol, MSG, detoxes, eight glasses of water, the five-second rule, best-by dates: 13 food myths, checked against FDA, USDA and research.](https://erroneo.us/myths/nutrition-myths/)
- [Myths Money mistakes and personal-finance myths Minimum payments, credit-check myths, skipped 401(k) matches, fee drag, market timing, forgotten subscriptions and scams: 13 money mistakes, with sources.](https://erroneo.us/myths/money-mistakes/)
## Myth or Fact?
Swipe right for **fact**, left for **myth** (or use the buttons, or your arrow keys). Every verdict links to a cited source.
**All 22 claims with verdicts and sources**
1. We only use 10% of our brains.
**Reveal the verdict**
MYTH Over a day, virtually all of the brain is used. It is about 3% of body weight but consumes about 20% of the body's energy. [Read more](https://erroneo.us/myths/science-myths/#1-we-only-use-10-of-our-brains) · Source: [Scientific American, Do People Only Use 10 Percent of Their Brains?](https://www.scientificamerican.com/article/do-people-only-use-10-percent-of-their-brains/)
2. The Great Wall of China is easy to see from space, even from the Moon.
**Reveal the verdict**
MYTH China's first astronaut, Yang Liwei, said in 2003 that he had not seen the wall. It is narrow and blends with the surrounding terrain; the Moon version dates at least to a 1932 Ripley's cartoon. [Read more](https://erroneo.us/myths/science-myths/#2-the-great-wall-of-china-is-visible-from-space) · Source: [Scientific American (2008), Is China's Great Wall Visible from Space?](https://www.scientificamerican.com/article/is-chinas-great-wall-visible-from-space/)
3. Goldfish have a three-second memory.
**Reveal the verdict**
MYTH In a 1994 study, goldfish learned to press a lever for food only during a one-hour daily window, kept that schedule over four weeks, and kept anticipating it for several days after food stopped. [Read more](https://erroneo.us/myths/science-myths/#3-goldfish-have-a-three-second-memory) · Source: [Gee, Stephenson & Wright (1994), Temporal discrimination learning of operant feeding in goldfish, JEAB](https://doi.org/10.1901/jeab.1994.62-1)
4. Different zones of the tongue taste sweet, sour, salty and bitter.
**Reveal the verdict**
MYTH Taste receptor cells for each basic quality are found in taste buds throughout the tongue and mouth. [Read more](https://erroneo.us/myths/science-myths/#6-different-parts-of-the-tongue-taste-different-things) · Source: [Chandrashekar et al. (2006), The receptors and cells for mammalian taste, Nature](https://doi.org/10.1038/nature05401)
5. Cracking your knuckles causes arthritis.
**Reveal the verdict**
MYTH A 2011 case-control study of 215 people found osteoarthritis in 18.1% of knuckle crackers and 21.5% of non-crackers, not a significant difference. [Read more](https://erroneo.us/myths/science-myths/#8-cracking-your-knuckles-causes-arthritis) · Source: [deWeber, Olszewski & Ortolano (2011), Knuckle cracking and hand osteoarthritis, JABFM](https://doi.org/10.3122/jabfm.2011.02.100156)
6. Lightning often strikes the same place repeatedly.
**Reveal the verdict**
FACT The US National Weather Service says lightning often strikes the same place repeatedly, especially tall, pointy, isolated objects. The Empire State Building is hit an average of 23 times a year. [Read more](https://erroneo.us/myths/science-myths/#5-lightning-never-strikes-the-same-place-twice) · Source: [National Weather Service, Lightning Myths](https://www.weather.gov/safety/lightning-myths)
7. Earth is closest to the Sun in January.
**Reveal the verdict**
FACT Earth reaches perihelion, about 91.4 million miles, in January and aphelion, about 94.5 million miles, in July. The seasons come from Earth's tilted axis, not its distance from the Sun. [Read more](https://erroneo.us/myths/science-myths/#9-summer-happens-when-earth-is-closest-to-the-sun) · Source: [NASA Space Place, What Causes the Seasons?](https://spaceplace.nasa.gov/seasons/en/)
8. Napoleon was unusually short for his time.
**Reveal the verdict**
MYTH Three sources, including his physician, put him at about 1.67 m, just under 5 ft 6 in, which was slightly above average for a Frenchman of the period. [Read more](https://erroneo.us/myths/history-myths/#1-napoleon-was-unusually-short) · Source: [History.com, Was Napoleon Short? Origins of the 'Napoleon Complex'](https://www.history.com/articles/napoleon-complex-short)
9. Vikings wore horned helmets into battle.
**Reveal the verdict**
MYTH The National Museum of Denmark calls the image a myth, partly because no such headgear of a Viking Age date has ever been found. [Read more](https://erroneo.us/myths/history-myths/#2-vikings-wore-horned-helmets) · Source: [National Museum of Denmark, Berserkers (on horned helmets)](https://en.natmus.dk/historical-knowledge/denmark/prehistoric-period-until-1050-ad/the-viking-age/weapons/berserkers/)
10. Albert Einstein failed mathematics at school.
**Reveal the verdict**
MYTH Shown a 1935 Ripley's clipping claiming he failed, Einstein said he never failed in mathematics and had mastered differential and integral calculus before he was fifteen. [Read more](https://erroneo.us/myths/history-myths/#4-einstein-failed-mathematics) · Source: [TIME, Did Einstein flunk math?](https://content.time.com/time/specials/packages/article/0,28804,1936731_1936743_1936758,00.html)
11. Marie Antoinette said 'Let them eat cake.'
**Reveal the verdict**
MYTH Britannica says there is absolutely no historical evidence she said it. A version of the line appears in Rousseau's Confessions, written when she was still a child in Austria. [Read more](https://erroneo.us/myths/history-myths/#5-marie-antoinette-said-let-them-eat-cake) · Source: [Britannica, Did Marie-Antoinette Really Say 'Let Them Eat Cake'?](https://www.britannica.com/story/did-marie-antoinette-really-say-let-them-eat-cake)
12. The Salem 'witches' were hanged, not burned.
**Reveal the verdict**
FACT None of those executed at Salem in 1692 was burned. In accordance with English law, 19 were hanged. [Read more](https://erroneo.us/myths/history-myths/#7-the-salem-witches-were-burned-at-the-stake) · Source: [History.com, Were Witches Burned at the Stake During the Salem Witch Trials?](https://www.history.com/articles/were-witches-burned-at-the-stake-during-the-salem-witch-trials)
13. The first known iron maidens were built in the 19th century, not the Middle Ages.
**Reveal the verdict**
FACT The story was likely spread by Johann Philipp Siebenkees in the late 18th century; the first known iron maidens were constructed in the 19th century and passed off in museums as medieval. [Read more](https://erroneo.us/myths/history-myths/#8-the-iron-maiden-was-a-medieval-torture-device) · Source: [History.com, 7 Famous Torture Devices, Real and Mythical](https://www.history.com/articles/7-famous-torture-devices-medieval-iron)
14. Sugar makes kids hyperactive.
**Reveal the verdict**
MYTH A 1995 JAMA meta-analysis of 23 blinded, placebo-controlled studies concluded that sugar does not affect the behavior or cognitive performance of children. [Read more](https://erroneo.us/myths/nutrition-myths/#3-sugar-makes-kids-hyperactive) · Source: [Wolraich, Wilson & White (1995), The effect of sugar on behavior or cognition in children: a meta-analysis, JAMA (PubMed)](https://pubmed.ncbi.nlm.nih.gov/7474248/)
15. Searing meat seals in the juices.
**Reveal the verdict**
MYTH America's Test Kitchen seared one batch of rib-eyes before roasting and another after; both lost around 22 percent of their weight. Searing builds flavor, not juiciness. [Read more](https://erroneo.us/myths/nutrition-myths/#7-searing-meat-seals-in-the-juices) · Source: [America's Test Kitchen: Searing steak](https://www.americastestkitchen.com/how_tos/5699-searing-steak)
16. Cooking always burns off all the alcohol in a wine sauce.
**Reveal the verdict**
MYTH USDA retention data show a flamed dish keeps about 75% of its alcohol, and even simmering for 2.5 hours leaves about 5%. [Read more](https://erroneo.us/myths/nutrition-myths/#10-the-alcohol-cooks-off) · Source: [USDA Table of Nutrient Retention Factors, Release 6 (2007) (PDF)](https://www.ars.usda.gov/ARSUserFiles/80400525/Data/retn/retn06.pdf)
17. Brown eggs are healthier than white eggs.
**Reveal the verdict**
MYTH The USDA's Egg-Grading Manual says shell color does not affect the quality of the egg. Shell color comes from the hen's breed. [Read more](https://erroneo.us/myths/nutrition-myths/#11-brown-eggs-are-healthier-than-white) · Source: [USDA AMS Egg-Grading Manual (PDF)](https://www.ams.usda.gov/sites/default/files/EggGradingManual.pdf)
18. Microwaving is one of the gentlest ways to cook when it comes to nutrients.
**Reveal the verdict**
FACT Harvard Health calls microwave cooking one of the least likely forms of cooking to damage nutrients, because cooking times are short. [Read more](https://erroneo.us/myths/nutrition-myths/#8-microwaving-destroys-nutrients) · Source: [Harvard Health Publishing: Microwave cooking and nutrition](https://www.health.harvard.edu/staying-healthy/microwave-cooking-and-nutrition)
19. Food dropped on the floor can pick up bacteria in less than a second.
**Reveal the verdict**
FACT Rutgers researchers testing 128 scenarios found that some transfer takes place 'instantaneously', at times under one second. Longer contact meant more bacteria. [Read more](https://erroneo.us/myths/nutrition-myths/#9-the-five-second-rule) · Source: [Miranda & Schaffner (2016), Longer Contact Times Increase Cross-Contamination of Enterobacter aerogenes from Surfaces to Food, Appl Environ Microbiol (PubMed)](https://pubmed.ncbi.nlm.nih.gov/27590818/)
20. Checking your own credit report does not lower your credit score.
**Reveal the verdict**
FACT The CFPB lists your requests for your own credit reports as soft inquiries, which will not affect your credit scores. Hard inquiries, from applying for credit, can. [Read more](https://erroneo.us/myths/money-mistakes/#5-checking-your-credit-hurts-your-score) · Source: [CFPB: What is a credit inquiry?](https://www.consumerfinance.gov/ask-cfpb/what-is-a-credit-inquiry-en-1317/)
21. Closing old credit cards improves your credit score.
**Reveal the verdict**
MYTH In the FICO model, amounts owed make up 30% of the score. Closing an unused card lowers your total available credit, so the same balances push your utilization higher. [Read more](https://erroneo.us/myths/money-mistakes/#6-closing-old-cards-improves-your-credit) · Source: [myFICO: What's in my FICO Scores?](https://www.myfico.com/credit-education/whats-in-your-credit-score)
22. On a $100,000 portfolio over 20 years, a 1% annual fee instead of 0.25% can cost tens of thousands of dollars.
**Reveal the verdict**
FACT Investor.gov's illustration of a $100,000 portfolio growing 4% a year shows about $208,000 after 20 years at a 0.25% fee versus about $179,000 at 1.00%, a gap of roughly $29,000. [Read more](https://erroneo.us/myths/money-mistakes/#8-ignoring-fees-because-they-look-small) · Source: [SEC Investor.gov: Understanding Fees](https://www.investor.gov/introduction-investing/getting-started/understanding-fees)
## How a myth survives
Misconceptions spread for understandable reasons. Many began as a simplification that got repeated without its caveats. Others started as a real finding that was later revised, while the old version lived on in textbooks, packaging and family advice. A few were simply made up and became true-by-repetition.
That is why every myth in this section is paired with **where the correction comes from**: a space agency, a food-safety regulator, a national museum, a consumer-finance agency or the original study. If we can’t point at evidence, the claim doesn’t go on the page.
## What’s in this section
- [Science myths](https://erroneo.us/myths/science-myths/) — from the “10% of your brain” claim to the cause of the seasons.
- [History myths](https://erroneo.us/myths/history-myths/) — horned Viking helmets, a short Napoleon and other durable stories.
- [Nutrition & food myths](https://erroneo.us/myths/nutrition-myths/) — eggs, MSG, water, sugar and “best by” dates.
- [Money mistakes & myths](https://erroneo.us/myths/money-mistakes/) — credit scores, fees, emergency funds and scams.
>
**Not personal advice.** Health and money pages summarize published guidance for general readers. For decisions about your own diet, medication or finances, talk to a qualified professional.
---
Source page: https://erroneo.us/myths/ · More: https://erroneo.us/llms.txt
==========
---
title: "Thinking errors"
url: https://erroneo.us/thinking/
description: "Cognitive biases and logical fallacies explained with everyday examples, the research behind them, and practical ways to catch them in yourself."
type: section
section: "Thinking"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# Thinking errors
> The mistakes we make before we say a word — and the ones we make the moment we start arguing.
- [Thinking Cognitive biases: the predictable ways good minds go wrong A sourced guide to 20 common cognitive biases: anchoring, confirmation bias, sunk cost, Dunning-Kruger and more, with examples, fixes and replication caveats.](https://erroneo.us/thinking/cognitive-biases/)
- [Thinking Logical fallacies: how arguments break, with examples Straw man, ad hominem, false dilemma, slippery slope, post hoc and more: 20 logical fallacies explained with plain examples, Latin names and how to respond.](https://erroneo.us/thinking/logical-fallacies/)
## Biases vs. fallacies
These two ideas get mixed up constantly, so here is the short version. A **cognitive bias** is a systematic tilt in how people judge or decide: we lean on the first number we hear, we notice evidence that agrees with us, we overrate what is easy to recall. Biases are psychological; they happen whether or not anyone is arguing.
A **logical fallacy** is a defect in an argument: the conclusion doesn’t follow from the reasons given, even if it sounds as though it does. Fallacies are about the structure of reasoning, which is why philosophers, not psychologists, catalogued most of them.
| | Cognitive bias | Logical fallacy |
|---|---|---|
| What it is | A pattern in judgment | A flaw in an argument |
| Where it lives | In the thinker | In the reasoning as stated |
| Studied by | Psychology, behavioral economics | Logic, philosophy, rhetoric |
| Example | Anchoring on a list price | “Everyone buys it, so it must be good” |
## A note on evidence
Some famous findings in psychology have not held up when other labs repeated them. Where an effect is contested, our guides say so and link the replication work, instead of presenting a classic study as settled. Knowing which errors are well established is itself a guard against error.
---
Source page: https://erroneo.us/thinking/ · More: https://erroneo.us/llms.txt
==========
---
title: "Famous software bugs in history"
url: https://erroneo.us/developers/famous-software-bugs/
description: "Ariane 5, Mars Climate Orbiter, Therac-25, Knight Capital, the Patriot clock, Y2K and CrowdStrike: what went wrong, per official reports, and the lessons."
type: guide
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# Famous software bugs in history
> The bugs that crashed rockets, lost a Mars probe, overdosed patients and burned through hundreds of millions of dollars, told from the official investigation reports, with the lesson each one teaches.
Most bugs cost an afternoon. A few make history. The cases below are the ones engineers still teach, because each was investigated in public and each has a clear lesson. Wherever possible we've used the official inquiry, regulator or vendor report, and every cost or casualty figure is the one stated in the cited source.
| Incident | Year | Bug class | Impact (per source) |
|---|---|---|---|
| Therac-25 | 1985–87 | Race conditions, counter overflow | Six massive radiation overdoses, with deaths and serious injuries |
| Patriot missile, Dhahran | 1991 | Fixed-point rounding drift | Scud not intercepted, 28 soldiers killed |
| Pentium FDIV | 1994 | Missing lookup-table entries | Rare wrong division results, chip replacement program |
| Ariane 5 Flight 501 | 1996 | Integer overflow on conversion | Launcher destroyed about 39 s after liftoff |
| Mars Climate Orbiter | 1999 | Unit mismatch (lbf·s vs N·s) | Spacecraft lost on arrival at Mars |
| Y2K | 1999–2000 | Two-digit years | Mostly minor failures after very large remediation spending |
| Northeast blackout | 2003 | Silent alarm-software failure | About 50 million people affected |
| Knight Capital | 2012 | Dead code and a partial deploy | More than $460 million lost in about 45 minutes |
| CrowdStrike Channel File 291 | 2024 | Out-of-bounds read | About 8.5 million Windows devices crashed |
| Year 2038 | 2038 | 32-bit time overflow | Still ahead |
## Therac-25 (1985–1987): when software replaced the safety interlocks
The Therac-25 was a computer-controlled radiation therapy machine. In the definitive account, Nancy Leveson and Clark Turner report that [between June 1985 and January 1987, six known accidents involved massive overdoses](https://web.archive.org/web/20240909111858/http://www.cse.msu.edu/~cse470/Public/Handouts/Therac/Therac_1.html), with deaths and serious injuries. Eleven machines were installed, five in the US and six in Canada. Unlike its predecessors, the Therac-25 relied on software for safety functions that earlier models had backed up with independent hardware interlocks.
The investigators identified more than one software flaw. At Tyler, Texas, an operator who edited the treatment mode and returned to the command line within about 8 seconds, while the bending magnets were still being set, could leave the machine in an inconsistent state. It showed a cryptic "Malfunction 54" ([Leveson & Turner](https://web.archive.org/web/20250719153956/https://cse.msu.edu/~cse470/Public/Handouts/Therac/Therac_3.html)). At Yakima, Washington, a one-byte variable named `Class3` was incremented on every pass through a setup routine. When it rolled over to zero at the moment the operator pressed "set", a safety check was skipped. AECL's fix was to set the variable to a fixed non-zero value instead of incrementing it.
>
**Lesson:** don't remove hardware safety nets because "the software handles it", and treat operator-reported quirks as bug reports. Leveson and Turner also warn that [reusing software doesn't guarantee safety](https://web.archive.org/web/20260530170443/https://cse.msu.edu/~cse470/Public/Handouts/Therac/Therac_5.html).
## Patriot missile at Dhahran (25 February 1991): a tenth of a second that never quite added up
On 25 February 1991 a Patriot battery in Dhahran, Saudi Arabia, failed to intercept an Iraqi Scud, which struck a US Army barracks and [killed 28 soldiers](https://www-users.cse.umn.edu/~arnold/disasters/patriot.html). The [GAO's report IMTEC-92-26](https://www.gao.gov/products/imtec-92-26) was titled *Software Problem Led to System Failure*.
The system counted time in tenths of a second as an integer and converted it to seconds using a 24-bit register. Because 1/10 has no exact binary representation, every conversion was slightly off, and the error grew the longer the system ran. Mathematician Douglas Arnold works through the arithmetic in [his analysis](https://www-users.cse.umn.edu/~arnold/disasters/patriot.html): after about 100 hours of uptime the drift was about 0.34 seconds, enough for a Scud travelling around 1,676 m/s to fall outside the radar's "range gate".
>
**Lesson:** floating- and fixed-point errors accumulate, and "it works in testing" isn't "it works after 100 hours of uptime". Test long-running behaviour, and make time calculations exact.
## Pentium FDIV (1994): five missing table entries
Intel's Pentium used an SRT division algorithm driven by a lookup table. According to a summary hosted by [Earlham College's computer science department](https://www.cs.earlham.edu/~dusko/cs63/fdiv.html), citing *Byte* (March 1995), five of the table's 1,066 entries were not loaded into the chip's programmable logic array, so they read as zero instead of +2. Intel characterised the chance of a random divide producing an inaccurate result as about 1 in 9 billion. The well-known test case `4195835 / 3145727` came back wrong in the fifth significant digit. Intel eventually offered no-questions-asked replacements.
>
**Lesson:** "rare" isn't the same as "harmless" when millions of units run billions of operations. Users' trust also depends on how openly you disclose a flaw.
## Ariane 5 Flight 501 (4 June 1996): reused code, new rocket
Ariane 5's maiden flight flew normally until about 37 seconds after ignition. The launcher then veered off course and began to disintegrate at about H0 + 39 seconds. The [Inquiry Board](https://www-users.cse.umn.edu/~arnold/disasters/ariane5rep.html) found that both inertial reference units had shut down. The backup failed first, one 72-millisecond data cycle earlier, "for the same reason" as the active unit.
The cause was "a data conversion from 64-bit floating point to 16-bit signed integer value". The value, the horizontal bias `BH`, was too large to fit and triggered an Operand Error. Other conversions in the same code were protected. This one wasn't, because analysis based on Ariane 4 said it couldn't overflow. Ariane 5's early trajectory was different, so it did. The Board also noted that the alignment code in which the error occurred "serves no purpose" after liftoff.
Wrong: ~~It flew fine on Ariane 4, so it's safe to reuse unchanged.~~
Right: Reused code inherits assumptions. Re-validate them against the new system's actual operating range.
## Mars Climate Orbiter (23 September 1999): pounds vs newtons
NASA lost contact with the Mars Climate Orbiter during its orbit-insertion burn on 23 September 1999. The [Mishap Investigation Board's Phase I report](https://llis.nasa.gov/llis_lib/pdf/1009464main1_0641-mr.pdf) found that ground software called `SM_FORCES` reported thruster impulse data in English units of pound-force seconds, while the project's software interface specification required metric newton-seconds. Navigation models therefore underestimated small trajectory effects by a factor of 4.45. The minimum survivable altitude was 80 km. After-the-fact estimates put the actual periapsis at about 57 km.
```
# What the interface required vs what was delivered
impulse_lbf_s = 1.0
impulse_n_s = impulse_lbf_s * 4.45 # conversion that never happened
```
>
**Lesson:** put units in types, field names or schemas, verify interfaces end to end, and treat navigation anomalies that people noticed as blockers. The Board's contributing causes also included a verification and validation process that didn't adequately cover ground software, and inadequate communications between project elements.
## Y2K (1999–2000): the bug that mostly didn't happen
For decades, many programs stored years as two digits, so `00` couldn't be told apart from 1900. Remediation was enormous. The research firm IDC estimated US preparation spending at about $134 billion, and worldwide estimates exceeded $300 billion, as summarised on [Wikipedia's Year 2000 problem article](https://en.wikipedia.org/wiki/Year_2000_problem). The failures that did occur on 1 January 2000 were mostly minor, such as websites showing the year "19100".
>
**Myth check:** "Y2K was a hoax" gets the cause backwards. The rollover was quiet *because* the remediation work was done. That kind of hindsight error is covered on our [cognitive biases](https://erroneo.us/thinking/cognitive-biases/) page.
## The 2003 Northeast blackout: an alarm that failed silently
On 14 August 2003 a blackout hit an area with an estimated 50 million people and 61,800 MW of load in the US and Canada ([U.S.-Canada Task Force final report](https://www.energy.gov/sites/default/files/oeprod/DocumentsandMedia/BlackoutFinal-Web.pdf)). Overgrown trees tripping transmission lines were a primary cause. A software failure turned that into a cascade. Shortly after 14:14 EDT, FirstEnergy's alarm and logging software failed. Operators "did not know that they were operating without alarms", so they kept trusting a view of the grid that had stopped updating.
>
**Lesson:** monitoring needs its own monitoring. A dashboard showing no alerts should never look the same as a dashboard that has stopped working. Heartbeats and "last updated" timestamps prevent that.
## Knight Capital (1 August 2012): dead code, a repurposed flag, one server
The [SEC's order](https://www.sec.gov/files/litigation/admin/2013/34-70694.pdf) lays out the sequence in unusual detail. Knight's order router, SMARS, still contained "Power Peg", a feature unused since 2003. New code for NYSE's Retail Liquidity Program reused the flag that used to activate Power Peg. A technician deployed the new code to only seven of the eight SMARS servers, and no second person reviewed the deployment. When the market opened, orders carrying the repurposed flag reached the eighth server and woke up Power Peg.
In about 45 minutes, while processing 212 customer orders, SMARS produced more than 4 million executions in 154 stocks, for over 397 million shares. Knight lost more than $460 million ([SEC press release](https://www.sec.gov/newsroom/press-releases/2013-222)) and later paid a $12 million penalty. Before the open, Knight's systems had sent 97 automated emails flagging "Power Peg disabled". They weren't designed as alerts, and nobody acted on them.
- Delete dead code instead of leaving it callable.
- Never reuse a flag or field for a new meaning.
- Automate deployments and verify every target got the same build.
- Have a kill switch, and make alerts that matter look like alerts.
## CrowdStrike Channel File 291 (19 July 2024): 21 fields expected, 20 provided
At 04:09 UTC on 19 July 2024, CrowdStrike pushed a configuration update to its Falcon sensor for Windows that [triggered a logic error and blue-screen crashes](https://www.crowdstrike.com/en-us/blog/falcon-update-for-windows-hosts-technical-details/). It was reverted at 05:27 UTC. Microsoft estimated that [8.5 million Windows devices](https://blogs.microsoft.com/blog/2024/07/20/helping-our-customers-through-the-crowdstrike-outage/) were affected, which it described as less than one percent of all Windows machines.
According to CrowdStrike's [root cause analysis](https://www.crowdstrike.com/wp-content/uploads/2024/08/Channel-File-291-Incident-Root-Cause-Analysis-08.06.2024.pdf), a template type introduced with sensor 7.11 defined 21 input fields, but the integration code supplied only 20. Earlier content used a wildcard for the 21st field, so nothing read it. The 19 July content was the first to match on that field, and the Content Interpreter performed an out-of-bounds read. Fixes included runtime bounds checks and staged rollouts for this kind of content.
>
**Lesson:** configuration is code. Anything that can crash a kernel-level component deserves the same validation, bounds checks and gradual rollout as a binary release.
## The Year 2038 problem: the next rollover
Unix-like systems traditionally store time as a signed 32-bit count of seconds since 1970-01-01. The [glibc project's design notes](https://sourceware.org/glibc/wiki/Y2038ProofnessDesign) state that this value rolls over past +2,147,483,647 at **2038-01-19 03:14:07 UTC**, possibly jumping back to 1901-12-13. 64-bit platforms already use a 64-bit `time_t`. The risk is in 32-bit embedded devices, file formats and databases that store 32-bit timestamps, and code that computes future dates (a 20-year certificate or mortgage, for example) long before 2038.
```
>>> 2**31 - 1
2147483647 # seconds after 1970-01-01T00:00:00Z → 2038-01-19T03:14:07Z
```
## Patterns that keep repeating
| Pattern | Seen in | Defence |
|---|---|---|
| Assumptions from an old context | Ariane 5, Therac-25 | Re-validate reused code against new operating ranges |
| Numeric representation limits | Ariane 5, Patriot, Y2K, 2038 | Checked conversions, wide types, explicit overflow handling |
| Interface mismatches | Mars Climate Orbiter, CrowdStrike | Typed schemas, units in names, contract tests |
| Silent failure | 2003 blackout, Knight Capital | Heartbeats, real alerts, monitoring the monitors |
| Risky rollout | Knight Capital, CrowdStrike | Automated, staged, verifiable deploys with a kill switch |
For the everyday versions of these mistakes, see our guides to [JavaScript errors](https://erroneo.us/developers/javascript-errors/) and [Python errors](https://erroneo.us/developers/python-errors/).
## Frequently asked questions
**What is the most expensive software bug in history?**
There is no reliable single ranking, because costs are counted in very different ways (lost hardware, trading losses, remediation spending, economic disruption). Among well-documented cases, the SEC found that Knight Capital lost more than $460 million in about 45 minutes in 2012, and estimates of worldwide Y2K remediation spending run into the hundreds of billions of dollars.
**Was the Mars Climate Orbiter lost because of metric vs imperial units?**
Yes. NASA's Mishap Investigation Board found the root cause was ground software (SM_FORCES) that reported thruster impulse in pound-force seconds when the interface specification required newton-seconds, a factor of 4.45. The resulting navigation error put the spacecraft far too close to Mars.
**What caused the Ariane 5 explosion?**
On 4 June 1996, software in both inertial reference units failed when converting a 64-bit floating-point value (horizontal bias, BH) to a 16-bit signed integer that was too small to hold it. The code had been reused from Ariane 4, whose trajectory never produced values that large, and the function served no purpose after liftoff.
**What is the Year 2038 problem?**
Systems that store time as a signed 32-bit count of seconds since 1 January 1970 will overflow at 03:14:07 UTC on 19 January 2038, and may wrap back to 1901. Modern 64-bit systems use a 64-bit time value, but embedded devices, old file formats and 32-bit software can still be affected.
## Sources
1. [ARIANE 5 Flight 501 Failure: Report by the Inquiry Board (1996), text mirror at University of Minnesota](https://www-users.cse.umn.edu/~arnold/disasters/ariane5rep.html)
2. [NASA: Mars Climate Orbiter Mishap Investigation Board Phase I Report (10 November 1999)](https://llis.nasa.gov/llis_lib/pdf/1009464main1_0641-mr.pdf)
3. [Leveson & Turner, An Investigation of the Therac-25 Accidents, IEEE Computer, 1993 (Michigan State University course copy, archived)](https://web.archive.org/web/20240909111858/http://www.cse.msu.edu/~cse470/Public/Handouts/Therac/Therac_1.html)
4. [U.S. SEC press release 2013-222: SEC Charges Knight Capital With Violations of Market Access Rule](https://www.sec.gov/newsroom/press-releases/2013-222)
5. [U.S. SEC Order, In the Matter of Knight Capital Americas LLC, Release No. 34-70694](https://www.sec.gov/files/litigation/admin/2013/34-70694.pdf)
6. [GAO/IMTEC-92-26: Patriot Missile Defense: Software Problem Led to System Failure at Dhahran, Saudi Arabia](https://www.gao.gov/products/imtec-92-26)
7. [Douglas N. Arnold (University of Minnesota): The Patriot Missile Failure](https://www-users.cse.umn.edu/~arnold/disasters/patriot.html)
8. [Earlham College CS: Bugs in the Intel Microprocessors (Pentium FDIV)](https://www.cs.earlham.edu/~dusko/cs63/fdiv.html)
9. [U.S.-Canada Power System Outage Task Force: Final Report on the August 14, 2003 Blackout](https://www.energy.gov/sites/default/files/oeprod/DocumentsandMedia/BlackoutFinal-Web.pdf)
10. [CrowdStrike: Falcon Update for Windows Hosts, Technical Details](https://www.crowdstrike.com/en-us/blog/falcon-update-for-windows-hosts-technical-details/)
11. [CrowdStrike: Channel File 291 Incident Root Cause Analysis (6 August 2024)](https://www.crowdstrike.com/wp-content/uploads/2024/08/Channel-File-291-Incident-Root-Cause-Analysis-08.06.2024.pdf)
12. [Microsoft: Helping our customers through the CrowdStrike outage (20 July 2024)](https://blogs.microsoft.com/blog/2024/07/20/helping-our-customers-through-the-crowdstrike-outage/)
13. [Wikipedia: Year 2000 problem](https://en.wikipedia.org/wiki/Year_2000_problem)
14. [glibc wiki: Y2038 Proofness Design](https://sourceware.org/glibc/wiki/Y2038ProofnessDesign)
---
Source page: https://erroneo.us/developers/famous-software-bugs/ · More: https://erroneo.us/llms.txt
==========
---
title: "401 Unauthorized vs 403 Forbidden"
url: https://erroneo.us/developers/http-401-vs-403/
description: "401 means authenticate and try again; 403 means credentials will not help. The RFC 9110 rules, OAuth bearer-token cases, and when 404 is the safer answer."
type: guide
section: "Developers"
date_modified: 2026-10-22
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# 401 Unauthorized vs 403 Forbidden
> Two codes, one question: would logging in (again) change the answer? If yes, send 401. If no, send 403. Here is the spec behind that rule and the edge cases that trip people up.
401 and 403 are the most commonly swapped pair of status codes on the web, partly because their names are misleading. "Unauthorized" sounds like a permissions problem, but in HTTP it is about *authentication*: who you are. "Forbidden" is about *authorization*: what you are allowed to do. Once you separate those two ideas, choosing the code is easy.
## What the spec actually says
[RFC 9110 §15.5.2](https://www.rfc-editor.org/rfc/rfc9110#name-401-unauthorized) defines 401 as a request that "has not been applied because it lacks valid authentication credentials for the target resource." It adds a hard requirement: the server "MUST send a WWW-Authenticate header field … containing at least one challenge." A 401 is therefore an invitation: here is how to authenticate, please try again.
[RFC 9110 §15.5.4](https://www.rfc-editor.org/rfc/rfc9110#name-403-forbidden) defines 403 as the server having "understood the request but refuses to fulfill it." If credentials were provided, "the server considers them insufficient to grant access," and the client "SHOULD NOT automatically repeat the request with the same credentials." It also notes that a request "might be forbidden for reasons unrelated to the credentials," such as an IP block.
[MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403) sums it up neatly: for 403, "authenticating or re-authenticating makes no difference."
| | `401 Unauthorized` | `403 Forbidden` |
|---|---|---|
| Question it answers | Who are you? | You are not allowed to do this |
| Concept | Authentication | Authorization (or a policy block) |
| Required header | `WWW-Authenticate` (MUST) | None |
| Will logging in help? | Yes | No |
| Client should | Obtain or refresh credentials, retry | Stop, or try *different* credentials |
| Typical trigger | Missing, expired, revoked or malformed token or session | Wrong role, missing scope, IP/WAF block, file permissions |
## The decision rule
1. **No credentials at all?** Send `401` with a challenge.
2. **Credentials present but invalid or expired?** Send `401`. The client should log in again or refresh its token.
3. **Credentials valid, but this identity may not do this?** Send `403`.
4. **Should this caller even learn the resource exists?** If not, send `404` instead of 403. RFC 9110 allows exactly this: a server that wishes to "hide" a forbidden resource "MAY instead respond with a status code of 404."
## OAuth and bearer tokens
Most modern APIs use bearer tokens, and [RFC 6750 §3.1](https://www.rfc-editor.org/rfc/rfc6750#section-3.1) spells out the mapping precisely:
| Error code in `WWW-Authenticate` | Meaning (RFC 6750) | Status |
|---|---|---|
| `invalid_request` | Missing or duplicated parameter, otherwise malformed | `400` |
| `invalid_token` | Token expired, revoked, malformed or otherwise invalid | `401` |
| `insufficient_scope` | Token valid but needs higher privileges | `403` |
| (no error code) | Request had no authentication information at all | `401` |
```
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="example", error="invalid_token",
error_description="The access token expired"
```
```
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer realm="example", error="insufficient_scope",
scope="invoices:write"
```
RFC 6750 also says that when a request has no authentication information, the server "SHOULD NOT include an error code or other error information," so the minimal challenge is just `WWW-Authenticate: Bearer realm="example"`.
## Wrong vs right
Wrong: ~~Logged-out user requests `/account` → `403 Forbidden`~~
Right: `401 Unauthorized` + `WWW-Authenticate` (API), or a `302`/`303` to the login page (browser app)
Why: A 403 tells the client that logging in will not help, so well-behaved clients will not try. For HTML pages, many sites redirect to a login form instead; that is fine as long as API endpoints still return a real 401.
Wrong: ~~Expired JWT → `403 Forbidden`~~
Right: Expired JWT → `401` with `error="invalid_token"`
Why: Client libraries commonly use a 401 as the trigger to refresh the token and retry. A 403 breaks that flow and logs users out for no reason.
Wrong: ~~`401` with no `WWW-Authenticate` header~~
Right: `401` always carries at least one challenge
Why: It is a MUST in RFC 9110. If you genuinely have no challenge to offer (for example a cookie-session web app), consider whether a redirect to login or a 403 better describes the situation.
Wrong: ~~Regular user tries `DELETE /admin/users/42` → `401`~~
Right: `403 Forbidden`, with a body that says the action needs the admin role
Why: The user is authenticated; asking them to authenticate again is a loop. MDN's own [403 example](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403) is exactly this case.
## Common causes of a 403 you did not expect
If you are seeing 403s and your permission logic looks correct, the refusal often comes from somewhere other than your application code:
| Cause | Where to look |
|---|---|
| Web server cannot read the file or directory | File ownership and permissions; nginx/Apache error log |
| Directory with no index file and listing disabled | Missing `index.html`; nginx logs a "directory index of … is forbidden" error |
| WAF, bot protection or CDN rule | CDN or firewall dashboard; response headers that name the vendor |
| IP allowlist or geo-block | Server `allow`/`deny` rules, cloud security groups |
| CSRF check failed | Framework logs; [Django, for example, returns a 403](https://docs.djangoproject.com/en/5.2/ref/csrf/) when the CSRF token is missing or wrong |
| Signed URL expired or signature mismatch | Object storage error body (for example S3's `AccessDenied`) |
| API rate limit reported as 403 | Some APIs do this: [GitHub returns 403 or 429](https://docs.github.com/en/rest/using-the-rest-api/troubleshooting-the-rest-api) for primary rate limits, with `x-ratelimit-remaining: 0` |
## How to debug
```
# See the status line and the challenge header
curl -i https://api.example.com/v1/me
# Same request with a token: did the status change?
curl -i -H "Authorization: Bearer $TOKEN" https://api.example.com/v1/me
```
If the code is `401` without the token and still `401` with it, the token itself is the problem: check expiry, audience, issuer and clock skew. If it moves from `401` to `403`, authentication works and the issue is permissions or scope. If it is `403` both times, the block is probably happening before your auth layer runs (WAF, IP rules, file permissions).
### If you are a visitor
- Sign out and back in, or clear cookies for the site, to fix a stale session (that turns a 401 into a 200).
- For a 403, check you are signed in with the right account; a work and a personal account are easy to mix up.
- Turn off a VPN or proxy briefly. IP-based blocks and bot protection often show up as 403.
- If none of that helps, the site has decided you may not see the page. Contact its owner.
## SEO notes
Google's documentation says [4xx codes other than 429 have no effect on crawl rate](https://developers.google.com/search/docs/crawling-indexing/http-network-errors), and that indexed URLs returning 4xx are removed from the index. It specifically says: "Don't use 401 and 403 status codes for limiting the crawl rate." If you want crawlers to slow down, that is a job for [429](https://erroneo.us/developers/http-429-too-many-requests/) or 503, not an authentication error.
>
Whatever you choose, put a machine-readable explanation in the body. [RFC 9457 problem details](https://www.rfc-editor.org/rfc/rfc9457) (`application/problem+json`) give you standard `type`, `title`, `status` and `detail` fields, which saves every client from guessing what "Forbidden" meant this time.
## From the Error of the Day
1. Oct 22 Developers[CORS errors: the server answered, the browser said no](https://erroneo.us/daily/cors-error/) A CORS error means the browser refused to hand your script the response. The server often answered fine. Fix it with server headers, not frontend hacks.
## Frequently asked questions
**What is the difference between 401 and 403?**
401 Unauthorized means the request lacks valid authentication credentials, and the server must send a WWW-Authenticate challenge. 403 Forbidden means the server understood the request and refuses it; if credentials were sent, they are insufficient, and retrying with the same ones will not help.
**Why is 401 called Unauthorized if it is about authentication?**
It is a historical naming quirk. The name dates from early HTTP, but the definition in RFC 9110 is clearly about missing or invalid authentication credentials, not about permissions.
**Should an expired token return 401 or 403?**
401. RFC 6750, which defines OAuth 2.0 bearer tokens, says an expired, revoked or malformed token is invalid_token and the server should respond with 401. A valid token that lacks the needed scope is insufficient_scope and gets 403.
**Is it OK to return 404 instead of 403?**
Yes, when revealing that a resource exists would itself leak information. RFC 9110 explicitly allows a server that wants to hide a forbidden resource to respond with 404. GitHub does this for private repositories.
**Does a 401 or 403 hurt SEO?**
Google says 4xx codes other than 429 do not affect crawl rate, but indexed URLs that return 4xx are removed from the index. Google also warns not to use 401 or 403 to limit crawl rate.
## Sources
1. [RFC 9110 §15.5.2: 401 Unauthorized](https://www.rfc-editor.org/rfc/rfc9110#name-401-unauthorized)
2. [RFC 9110 §15.5.4: 403 Forbidden](https://www.rfc-editor.org/rfc/rfc9110#name-403-forbidden)
3. [RFC 9110 §11.6.1: WWW-Authenticate](https://www.rfc-editor.org/rfc/rfc9110#name-www-authenticate)
4. [RFC 6750: OAuth 2.0 Bearer Token Usage, §3.1 Error Codes](https://www.rfc-editor.org/rfc/rfc6750#section-3.1)
5. [MDN: 403 Forbidden](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403)
6. [MDN: 401 Unauthorized](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401)
7. [GitHub Docs: Troubleshooting the REST API](https://docs.github.com/en/rest/using-the-rest-api/troubleshooting-the-rest-api)
8. [Google Search Central: How HTTP status codes affect Google Search](https://developers.google.com/search/docs/crawling-indexing/http-network-errors)
9. [RFC 9457: Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457)
10. [Django documentation: Cross Site Request Forgery protection](https://docs.djangoproject.com/en/5.2/ref/csrf/)
---
Source page: https://erroneo.us/developers/http-401-vs-403/ · More: https://erroneo.us/llms.txt
==========
---
title: "404 Not Found"
url: https://erroneo.us/developers/http-404-not-found/
description: "What HTTP 404 Not Found really means under RFC 9110, how it differs from 410 Gone, why soft 404s hurt SEO, and how to find and fix broken URLs on your site."
type: guide
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# 404 Not Found
> The web's most famous error is also one of its most misunderstood. A 404 is not a failure to be hidden; it is an honest answer, and the real mistakes are serving it wrongly or not serving it at all.
A 404 is the server saying, "I have nothing for that address." That is often exactly the right answer: someone mistyped a URL, an old link points at a page you deleted, or a bot is probing for `/wp-login.php` on a site that has never run WordPress. The errors worth fixing are the ones where a 404 hides a real problem, or where a page that does not exist pretends that it does.
## What 404 means, precisely
[RFC 9110 §15.5.5](https://www.rfc-editor.org/rfc/rfc9110#name-404-not-found) says a 404 "indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists." Two details in that sentence matter:
- **"Current representation."** The resource might exist later, or might have existed before. A 404 makes no claim either way. The RFC states that it "does not indicate whether this lack of representation is temporary or permanent."
- **"Not willing to disclose."** A 404 can be a deliberate privacy choice. RFC 9110's 403 section explicitly allows a server to answer 404 to "hide" a forbidden resource. [GitHub documents](https://docs.github.com/en/rest/using-the-rest-api/troubleshooting-the-rest-api) that its API returns 404 rather than 403 "to avoid confirming the existence of private repositories."
The RFC also notes that a 404 is heuristically cacheable, so a CDN or browser may keep serving a 404 for a while after you publish the missing page. If a freshly created page still 404s, purge the cache before you start debugging routes.
## 404 vs 410 Gone
[RFC 9110 §15.5.11](https://www.rfc-editor.org/rfc/rfc9110#name-410-gone) defines 410 as "no longer available at the origin server" with a condition that "is likely to be permanent." It describes the purpose as helping web maintenance by signalling that the resource is "intentionally unavailable" and that the owners want links to it removed, giving limited-time promotions and departed staff pages as examples.
| | `404 Not Found` | `410 Gone` |
|---|---|---|
| Claim | Nothing here (now), or not telling | It was here, it is gone on purpose |
| Permanence | Unspecified | Likely permanent |
| Use when | Unknown URLs, typos, or you are unsure | You deliberately removed it and there is no replacement |
| Google Search | Removed from the index | Removed from the index; Google documents no different treatment |
On that last row: Google's status-code documentation [groups all 4xx codes except 429 together](https://developers.google.com/search/docs/crawling-indexing/http-network-errors), saying indexed URLs returning them are removed from the index. It does not promise that 410 is processed faster. Use 410 because it is more truthful, not as an SEO trick.
## Soft 404s: the real mistake
A soft 404 is a page that looks like an error to a human but returns `200 OK`. Google's troubleshooting guide describes it as a URL "that returns a page telling the user that the page does not exist," and Search Console reports these as [soft 404 errors](https://developers.google.com/search/docs/crawling-indexing/troubleshoot-crawling-errors).
Wrong: ~~`HTTP/1.1 200 OK` … `
Sorry, we couldn't find that page
`~~
Right: `HTTP/1.1 404 Not Found` … the same friendly page, search box and links
Why: Your custom error page can be as helpful and charming as you like. It just has to be served with the right status code.
Google's guide lists three fixes, depending on the situation:
| Situation | Google's recommended response |
|---|---|
| Page removed, no similar replacement | Return `404` or `410` |
| Page moved, or has a clear replacement | Return a `301` to the replacement |
| Page is fine but was flagged anyway | It probably did not render properly for Googlebot (missing resources, an error message shown during rendering). Check it with the URL Inspection tool. |
The same guide lists causes such as "a missing server-side include file," "a broken connection to the database," and "an unloaded or otherwise missing JavaScript file." In other words, some soft 404s are really failed server responses wearing a 200.
### Single-page apps
Client-side routers are a classic source of soft 404s. The server returns `index.html` with a 200 for every path, then JavaScript renders a "not found" view. Options, from most to least robust:
- Let the server know the valid routes and return a real 404 for anything else (server-side rendering or a route manifest).
- For static hosting, only fall back to `index.html` for known route prefixes, and serve a static `404.html` with a 404 status for everything else.
- If neither is possible, have the not-found view add `` so the empty shell is not indexed.
```
# nginx: static site with clean URLs and an honest 404
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
```
In nginx, [`error_page`](https://nginx.org/en/docs/http/ngx_http_core_module.html) serves your custom page while keeping the 404 status. Be careful with the variant `error_page 404 =200 /404.html;`, which deliberately changes the status to 200 and creates a soft 404.
## Common causes of a 404
| Cause | Typical sign | Fix |
|---|---|---|
| Typo in a link or URL | One-off misses in logs | Fix the link; consider suggestions on the 404 page |
| Page deleted or renamed without a redirect | 404s that start the day of a redesign or migration | Add `301`s from old URLs to their replacements |
| Case sensitivity | Works on macOS, 404s on Linux | Lowercase URLs and file names consistently |
| Trailing slash mismatch | `/about` works, `/about/` does not (or vice versa) | Pick one form and redirect the other |
| Wrong route or HTTP method in an API | `POST /users/` vs `POST /users` | Check the router; a wrong method should be `405`, not 404 |
| Deployment missed files | Assets or new pages 404 right after deploy | Compare the build output with what is on the server |
| Stale cached 404 | Origin returns 200, users still see 404 | Purge the CDN/browser cache |
| Vulnerability scanners | Bursts of requests for `.env`, `wp-admin`, `phpmyadmin` | Nothing; these 404s are correct |
## How to debug
```
# What status does the URL really return?
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/pricing
# Check the old URL redirects where you think it does
curl -sIL https://example.com/old-pricing | grep -iE "^(HTTP|location)"
# Top 404 paths in an nginx access log (combined format: status is field 9)
awk '$9 == 404 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
```
The log query is the most useful of the three. A list of the most frequently requested missing paths tells you which redirects are worth adding; one-off misses usually are not. Search Console's Page indexing report gives you the same view from Google's side.
### If you are a visitor
- Check the URL for typos, stray punctuation, or an extra word pasted at the end.
- Remove parts of the path from the right until you reach a page that exists, then navigate from there.
- Use the site's own search, or a search engine with `site:example.com` and a few keywords.
- Try the Internet Archive's Wayback Machine for pages that have genuinely disappeared.
## A good 404 page
The status code is for machines; the page is for people. A useful 404 page says plainly that the page is not here, keeps your normal navigation, offers search, and links to the most popular sections. It should be lightweight and must not itself depend on the thing that might be broken. Our own [404 page](https://erroneo.us/404.html) has a little fun with the idea of an erroneous URL, which is also allowed.
>
Do not redirect every unknown URL to the homepage. Visitors lose the context of what they were looking for, and Google's guidance reserves 301s for cases with "a clear replacement." Blanket redirects are a common way to turn honest 404s into soft 404s.
## Frequently asked questions
**What does a 404 error mean?**
RFC 9110 says the origin server did not find a current representation for the target resource, or is not willing to disclose that one exists. It says nothing about whether the condition is temporary or permanent.
**What is the difference between 404 and 410?**
410 Gone means the resource is intentionally unavailable and the condition is likely permanent. RFC 9110 says 410 is preferred over 404 when the server knows the removal is permanent; if it does not know, 404 should be used.
**What is a soft 404?**
A page that tells the visitor it does not exist (or is empty) but returns a 2xx success status. Google detects these and reports them as soft 404 errors in Search Console. Fix it by returning a real 404 or 410, or a 301 if there is a genuine replacement.
**Do 404 errors hurt my SEO?**
Google says 4xx codes other than 429 do not affect crawl rate, and that indexed URLs returning 4xx are removed from the index. Missing pages that should not exist are normal; the problem is losing pages that should exist, or links that point to them.
**Should I redirect all 404s to the homepage?**
No. Google's guidance is to return 404 or 410 when a page is gone with no replacement and to use a 301 only when there is a clear replacement. Mass redirects to the homepage tend to be treated as soft 404s and confuse visitors.
## Sources
1. [RFC 9110 §15.5.5: 404 Not Found](https://www.rfc-editor.org/rfc/rfc9110#name-404-not-found)
2. [RFC 9110 §15.5.11: 410 Gone](https://www.rfc-editor.org/rfc/rfc9110#name-410-gone)
3. [RFC 9110 §15.5.4: 403 Forbidden (hiding a resource with 404)](https://www.rfc-editor.org/rfc/rfc9110#name-403-forbidden)
4. [Google Search Central: How HTTP status codes affect Google Search](https://developers.google.com/search/docs/crawling-indexing/http-network-errors)
5. [Google Search Central: Troubleshoot crawling errors (soft 404s)](https://developers.google.com/search/docs/crawling-indexing/troubleshoot-crawling-errors)
6. [MDN: 404 Not Found](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/404)
7. [GitHub Docs: Troubleshooting the REST API](https://docs.github.com/en/rest/using-the-rest-api/troubleshooting-the-rest-api)
8. [nginx: ngx_http_core_module (try_files, error_page)](https://nginx.org/en/docs/http/ngx_http_core_module.html)
---
Source page: https://erroneo.us/developers/http-404-not-found/ · More: https://erroneo.us/llms.txt
==========
---
title: "418 I’m a teapot, explained"
url: https://erroneo.us/developers/http-418-im-a-teapot/
description: "Where HTTP 418 I'm a teapot came from (RFC 2324, April 1998), why RFC 9110 reserves it as (Unused), and whether you should ever send it from a real API."
type: guide
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# 418 I’m a teapot, explained
> The most famous HTTP status code that isn’t really one: an April Fools’ joke from 1998 that was deployed so often the official HTTP specification had to fence it off.
HTTP/1.1 418 (Unused)
On 1 April 1998, Larry Masinter published [RFC 2324, the Hyper Text Coffee Pot Control Protocol](https://www.rfc-editor.org/rfc/rfc2324) (HTCPCP/1.0). It is a careful parody of how people were stretching HTTP to control everything, complete with a `BREW` method, a `WHEN` method (“Enough? Say WHEN.”) and a `coffee:` URI scheme. Section 2.3.2 added the line that outlived the joke:
>
Any attempt to brew coffee with a teapot should result in the error code “418 I’m a teapot”. The resulting entity body MAY be short and stout.
## Why the real HTTP spec reserves it
The joke escaped into real software, which created a real problem: a code that is widely deployed as a joke can’t safely be given a serious meaning later. So when the IETF consolidated HTTP semantics in RFC 9110, it gave 418 its own section, titled [418 (Unused)](https://www.rfc-editor.org/rfc/rfc9110#name-418-unused). It says the code “has been deployed as a joke often enough for the code to be unusable for any future use,” and is therefore reserved in the IANA registry. It also leaves a door open: if the 4xx range is ever exhausted, 418 can be reassigned.
Wrong: ~~`HTTP/1.1 418 I'm a teapot` to reject a request your API doesn’t like~~
Right: The real code for the situation: `400`, `403`, `422` or `429`
Why: RFC 9110 says a client that doesn’t recognise a status code [must treat it as the x00 code of its class](https://www.rfc-editor.org/rfc/rfc9110#name-status-codes). Your clever 418 becomes a plain 400 to every client, and a mystery to whoever reads the logs.
## The sequel: tea, officially
Sixteen years later, on 1 April 2014, [RFC 7168](https://www.rfc-editor.org/rfc/rfc7168) extended the protocol for “Tea Efflux Appliances” (HTCPCP-TEA), because the original “does not allow for the brewing of tea, in all its variety.” It also clarified the teapot’s options: a tea-capable pot that can’t brew coffee may return `503` to mean coffee is temporarily unavailable, or `418` “to denote a more permanent indication that the pot is a teapot.”
>
**Check the registry yourself.** The [IANA HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) lists 418 as `(Unused)`, referencing RFC 9110 Section 15.5.19. For the codes that do mean something, use the [status code explorer](https://erroneo.us/developers/http-status-codes/#status-code-explorer).
## What 418 teaches about real status codes
- **Codes are a contract.** Clients, caches and crawlers act on the number, so a code’s meaning has to stay stable for decades.
- **The class matters most.** Unknown codes fall back to `x00` of their class, which is why a wrong *class* does far more damage than an obscure specific code.
- **Jokes get deployed.** Anything you ship, people will depend on. That’s true of status codes and of the [famous software bugs](https://erroneo.us/developers/famous-software-bugs/) that became permanent behaviour.
## Frequently asked questions
**Is 418 I'm a teapot an official HTTP status code?**
Not in the usual sense. It was defined by RFC 2324, an April 1 joke RFC for the Hyper Text Coffee Pot Control Protocol. RFC 9110, the current HTTP semantics standard, lists 418 as (Unused) and reserves it in the IANA registry so it cannot be assigned to anything else for now.
**Why didn't the IETF just delete 418?**
RFC 9110 says the code has been deployed as a joke often enough to be unusable for any future use. Reassigning it would mean real clients could misread old joke responses, so it is reserved instead. The RFC adds that it could be reassigned if 4xx codes ever run out.
**Should my API return 418?**
No. Clients that do not recognise a code treat it as the x00 of its class, so a 418 is handled like 400 Bad Request, and nobody reading your logs will know what you meant. Use the real code for the situation, such as 400, 403, 422 or 429.
**What does a 418 response body look like?**
RFC 2324 says the resulting entity body "MAY be short and stout." That line, from the children's song, is the whole specification.
## Sources
1. [RFC 2324: Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0)](https://www.rfc-editor.org/rfc/rfc2324)
2. [RFC 7168: HTCPCP for Tea Efflux Appliances (HTCPCP-TEA)](https://www.rfc-editor.org/rfc/rfc7168)
3. [RFC 9110: HTTP Semantics, Section 15.5.19 (418 Unused)](https://www.rfc-editor.org/rfc/rfc9110#name-418-unused)
4. [RFC 9110: HTTP Semantics, Section 15 (Status Codes)](https://www.rfc-editor.org/rfc/rfc9110#name-status-codes)
5. [IANA HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
---
Source page: https://erroneo.us/developers/http-418-im-a-teapot/ · More: https://erroneo.us/llms.txt
==========
---
title: "429 Too Many Requests"
url: https://erroneo.us/developers/http-429-too-many-requests/
description: "HTTP 429 means you hit a rate limit. What RFC 6585 says, how to honor Retry-After, exponential backoff with jitter in code, and the new RateLimit headers draft."
type: guide
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# 429 Too Many Requests
> A 429 is the politest error in HTTP: it does not say you are wrong, only that you are early. Handling it well is mostly about waiting the right amount of time, and not all retrying at once.
Rate limits protect servers from being overwhelmed, whether by an abusive scraper, a buggy loop, or a perfectly legitimate customer who suddenly runs a big batch job. The status code that says "you have hit the limit" is `429 Too Many Requests`. Most 429 incidents are not caused by the limit itself but by what clients do next: retry immediately, retry in lockstep, or ignore the hint telling them when to come back.
## What the spec says
429 is not in the original HTTP/1.1 specs. It was added by [RFC 6585 §4](https://www.rfc-editor.org/rfc/rfc6585#section-4) in 2012, which says it "indicates that the user has sent too many requests in a given amount of time ('rate limiting')." The RFC adds three points worth knowing:
- The response "SHOULD include details explaining the condition, and MAY include a Retry-After header indicating how long to wait."
- The RFC "does not define how the origin server identifies the user, nor how it counts requests." Limits can be per IP, per API key, per account, per endpoint, or shared across a cluster.
- "Responses with the 429 status code MUST NOT be stored by a cache."
Its [security considerations](https://www.rfc-editor.org/rfc/rfc6585#section-7.2) also make a practical point: answering every request with a 429 still costs resources, so under real attack "it may be more appropriate to just drop connections." In other words, servers are not required to send 429, and a client that is hammering a server may see timeouts instead.
## Retry-After
[RFC 9110 §10.2.3](https://www.rfc-editor.org/rfc/rfc9110#name-retry-after) defines `Retry-After` as either an HTTP date or a number of seconds:
```
HTTP/1.1 429 Too Many Requests
Retry-After: 120
Content-Type: application/problem+json
{"type": "about:blank", "title": "Too Many Requests", "status": 429,
"detail": "Limit of 100 requests per minute exceeded for this API key."}
```
```
Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
```
Your client must handle both forms. A surprising number of hand-written clients parse only the integer, crash on the date form, and then fall back to retrying immediately.
## The RateLimit headers draft
For years APIs have invented their own quota headers (`X-RateLimit-Remaining` and friends; GitHub, for example, uses `x-ratelimit-remaining` and [sets it to 0 when you are limited](https://docs.github.com/en/rest/using-the-rest-api/troubleshooting-the-rest-api)). The IETF HTTP API working group is standardising this in [draft-ietf-httpapi-ratelimit-headers](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/), at version 11 as of May 2026 and still an Internet-Draft rather than an RFC. It defines two fields:
| Field | Parameters | Meaning |
|---|---|---|
| `RateLimit-Policy` | `q` quota, `w` window in seconds, optional `qu` unit and `pk` partition key | The rules: for example 100 requests per 60 seconds |
| `RateLimit` | `r` remaining quota, `t` seconds until the window resets, optional `pk` | Where you stand right now |
```
HTTP/1.1 200 OK
RateLimit-Policy: "basic";q=100;w=60
RateLimit: "basic";r=20;t=56
```
Those values come from the draft's own examples: 20 requests remain in a 100-per-minute policy, with 56 seconds left in the window. The draft says that if a response carries both fields, "the Retry-After field MUST take precedence." Because it is still a draft, treat these headers as useful hints and keep your client working when they are absent.
## Backoff with jitter
When there is no `Retry-After`, the standard approach is exponential backoff: wait a little, then twice as long, then twice as long again, up to a cap. The refinement that matters is *jitter*, a random element in each delay. Without it, every client that failed at the same moment retries at the same moment, and the spike repeats. In his widely cited AWS post [Exponential Backoff And Jitter](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/), Marc Brooker simulated contending clients and found jittered backoff cut the total call count by more than half compared with plain exponential backoff, concluding that it should be "considered a standard approach for remote clients." His "full jitter" variant picks a random delay between zero and the current exponential ceiling.
### JavaScript
```
function retryAfterMs(res) {
const h = res.headers.get("Retry-After");
if (!h) return null;
const secs = Number(h);
if (Number.isFinite(secs)) return Math.max(0, secs * 1000);
const when = Date.parse(h); // HTTP-date form
return Number.isNaN(when) ? null : Math.max(0, when - Date.now());
}
async function fetchWithBackoff(url, opts = {}, { tries = 5, base = 500, cap = 30000 } = {}) {
for (let attempt = 0; ; attempt++) {
const res = await fetch(url, opts);
if (res.status !== 429 && res.status !== 503) return res;
if (attempt + 1 >= tries) return res; // give up, let the caller decide
const hinted = retryAfterMs(res);
const ceiling = Math.min(cap, base * 2 ** attempt);
const delay = hinted ?? Math.random() * ceiling; // full jitter
await new Promise(r => setTimeout(r, delay));
}
}
```
### Python
```
import random, time
from email.utils import parsedate_to_datetime
from datetime import datetime, timezone
import requests
def retry_after_seconds(resp):
h = resp.headers.get("Retry-After")
if not h:
return None
if h.strip().isdigit():
return int(h)
try:
when = parsedate_to_datetime(h)
return max(0.0, (when - datetime.now(timezone.utc)).total_seconds())
except (TypeError, ValueError):
return None
def get_with_backoff(url, tries=5, base=0.5, cap=30.0, **kw):
for attempt in range(tries):
resp = requests.get(url, timeout=10, **kw)
if resp.status_code not in (429, 503) or attempt == tries - 1:
return resp
hinted = retry_after_seconds(resp)
delay = hinted if hinted is not None else random.uniform(0, min(cap, base * 2 ** attempt))
time.sleep(delay)
```
>
Only retry requests that are safe to repeat. A `GET` is fine; a `POST` that charges a card is not, unless the API supports an idempotency key. Rate-limited requests were usually not processed, but check the API's documentation rather than assuming.
## Wrong vs right
Wrong: ~~`while (res.status === 429) res = await fetch(url)`~~
Right: Honor `Retry-After`; otherwise back off exponentially with jitter, with a retry cap
Why: Immediate retries extend the overload you just caused, and on many APIs they count against your quota too.
Wrong: ~~Server rate limit returns `503 Service Unavailable`~~
Right: Per-client limits return `429`; reserve `503` for whole-service overload or maintenance
Why: The [nginx `limit_req` module](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html) defaults to `limit_req_status 503;`. Monitoring then pages someone because the service looks down, when really one client was too eager.
```
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
limit_req_status 429;
}
}
}
```
Wrong: ~~Using `403` to throttle search engine crawlers~~
Right: Use `429` or `503` briefly, or reduce load another way
Why: Google's docs say: "Don't use 401 and 403 status codes for limiting the crawl rate." Google treats 429 as [a signal that the server is overloaded](https://developers.google.com/search/docs/crawling-indexing/http-network-errors) and slows down; but persistent server errors can eventually drop URLs from the index, so this is a short-term measure.
## Common causes
| Cause | What it looks like | Fix |
|---|---|---|
| Loop or retry storm in your code | Hundreds of identical requests per second | Add backoff; cache results; fix the loop |
| Parallelism too high | Batch job runs fine with 2 workers, 429s with 50 | Limit concurrency; use a token bucket on the client |
| Shared IP | 429 on the first request from an office, VPN or CI runner | Authenticate so limits apply per key, not per IP |
| Wrong tier or plan | Limits far lower than expected | Check the API's published limits for your plan |
| Login throttling | 429 after several failed passwords | Wait; this limit is deliberate and protects your account |
| Polling instead of webhooks | Steady background traffic eating the quota | Switch to webhooks or conditional requests (ETags) |
### If you are a visitor
- Stop refreshing; each refresh can reset or extend the wait.
- Wait a minute or two, then try once.
- If you are on a shared network (VPN, office, mobile carrier), try another connection: you may be sharing a limit with many other people.
- Close extensions or scripts that might be polling the site in the background.
## Designing a limit people can live with
The [Handling Overload](https://sre.google/sre-book/handling-overload/) chapter of Google's SRE book argues for per-customer limits and for clients that throttle themselves before the server has to. In practice: publish your limits, send `Retry-After` on every 429, return the quota headers on successful responses too so clients can slow down before they hit the wall, and explain the limit in the body in plain language. A 429 that tells callers exactly what happened and when to come back is a 429 they will only see once.
## Frequently asked questions
**What does HTTP 429 mean?**
RFC 6585 defines 429 Too Many Requests as the user having sent too many requests in a given amount of time, which is rate limiting. The response may include a Retry-After header saying how long to wait.
**How long should I wait after a 429?**
If the response has a Retry-After header, wait at least that long; it can be a number of seconds or an HTTP date. If it does not, back off exponentially with random jitter, starting small and capping the maximum delay.
**Is 429 a client error or a server problem?**
It is a 4xx code, so formally the client is expected to change its behaviour (slow down). Google's crawlers, however, treat 429 like a server error, as a signal that the server is overloaded, and slow their crawling.
**Should rate limits return 429 or 503?**
429 when a specific caller has exceeded its allowance; 503 when the whole service is overloaded or in maintenance. nginx's limit_req returns 503 by default, which you can change with limit_req_status 429.
**What are the RateLimit and RateLimit-Policy headers?**
They come from an IETF HTTP API working group Internet-Draft (version 11, May 2026) that standardises how servers advertise quotas: RateLimit-Policy describes the policy, RateLimit reports the remaining quota and time window. It is not yet an RFC.
## Sources
1. [RFC 6585 §4: 429 Too Many Requests](https://www.rfc-editor.org/rfc/rfc6585#section-4)
2. [RFC 6585 §7.2: Security considerations for 429](https://www.rfc-editor.org/rfc/rfc6585#section-7.2)
3. [RFC 9110 §10.2.3: Retry-After](https://www.rfc-editor.org/rfc/rfc9110#name-retry-after)
4. [IETF draft-ietf-httpapi-ratelimit-headers](https://datatracker.ietf.org/doc/draft-ietf-httpapi-ratelimit-headers/)
5. [Marc Brooker, Exponential Backoff And Jitter (AWS Architecture Blog)](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/)
6. [nginx: ngx_http_limit_req_module](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html)
7. [Google Search Central: How HTTP status codes affect Google Search](https://developers.google.com/search/docs/crawling-indexing/http-network-errors)
8. [GitHub Docs: Troubleshooting the REST API (rate limits)](https://docs.github.com/en/rest/using-the-rest-api/troubleshooting-the-rest-api)
9. [MDN: 429 Too Many Requests](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429)
10. [Google SRE Book: Handling Overload](https://sre.google/sre-book/handling-overload/)
---
Source page: https://erroneo.us/developers/http-429-too-many-requests/ · More: https://erroneo.us/llms.txt
==========
---
title: "500 Internal Server Error"
url: https://erroneo.us/developers/http-500-internal-server-error/
description: "HTTP 500 means the server hit an unexpected condition. How to find the real cause in logs, the usual culprits, and why stack traces must never reach users."
type: guide
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# 500 Internal Server Error
> The vaguest status code in HTTP, on purpose. A 500 tells the outside world almost nothing, which is good for security and bad for debugging, unless you know where the real error went.
When a web application throws an exception that nothing catches, the framework or server has to send *something* back. That something is almost always `500 Internal Server Error`. It is the HTTP equivalent of a shrug, and by design it carries no detail. The useful information is in a log file somewhere, and the most common 500 mistake is not knowing where.
## What the spec says
[RFC 9110 §15.6.1](https://www.rfc-editor.org/rfc/rfc9110#name-500-internal-server-error) is one sentence long: a 500 "indicates that the server encountered an unexpected condition that prevented it from fulfilling the request." The surrounding [5xx section](https://www.rfc-editor.org/rfc/rfc9110#name-server-error-5xx) adds that the server "is aware that it has erred," and, except for HEAD requests, "SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition."
The key word is *unexpected*. If you can anticipate a failure, there is usually a more specific code: a bad request is a `400`, a missing record is a `404`, an upstream dependency that failed is often better described as [`502`, `503` or `504`](https://erroneo.us/developers/http-502-vs-504/). A 500 should mean "this is a bug or a broken environment."
Wrong: ~~Invalid email address in a signup form → `500` (the database constraint threw)~~
Right: Validate first and return `400` or `422` with the field that failed
Why: Every 500 you can trace to bad input is a missing validation step. The [OWASP Error Handling Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html) likewise suggests reserving 5xx for failures the server cannot handle and using 4xx for client-caused errors.
## Common causes
| Cause | Typical clue | Where to look |
|---|---|---|
| Unhandled exception in application code | Only certain pages or inputs fail | App log / error tracker stack trace |
| Null or undefined value | `TypeError`, `AttributeError`, `NullPointerException` | Stack trace; see [JavaScript errors](https://erroneo.us/developers/javascript-errors/) and [Python errors](https://erroneo.us/developers/python-errors/) |
| Missing environment variable or secret | Everything fails right after a deploy | Startup logs; diff config between environments |
| Database unreachable or migration not run | "relation does not exist", connection refused | App log; database log |
| File permission or path error | Uploads or templates fail | App log; web server error log |
| Bad server configuration | Every request on a virtual host fails | Web server error log; config test (`nginx -t`) |
| Dependency upgraded with breaking change | Started after an install or rebuild | Lockfile diff; changelog |
| Resource exhaustion | Fails under load, works at night | Memory, disk and file-descriptor metrics |
## How to debug a 500
### 1. Reproduce it and capture the request
```
# Status, headers and body in one go
curl -i https://example.com/checkout
# Many stacks return a request ID header; note it for the log search
curl -si https://example.com/checkout | grep -i -E "^(x-request-id|x-correlation-id|cf-ray):"
```
### 2. Read the right log
Work from the inside out. The error you need is usually in the first of these that exists:
1. **Your error tracker or application log.** This is where the stack trace lives.
2. **The application server's stdout/stderr.** On a systemd host, `journalctl -u myapp --since "10 min ago"`; in a container, `docker logs` or `kubectl logs`.
3. **The web server or reverse proxy error log.** For nginx, the path set by `error_log`, commonly `/var/log/nginx/error.log`. Caddy writes to its configured log output (often the systemd journal).
```
# Watch logs live while you reproduce the error
sudo tail -f /var/log/nginx/error.log
journalctl -u myapp -f
# Count 500s per path in an nginx access log (combined format)
awk '$9 == 500 {print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
```
### 3. Ask "what changed?"
Most 500s that appear suddenly coincide with a deploy, a config change, a dependency update, an expired credential or certificate, or a full disk. Check the deploy history before you start reading code.
### 4. Fix the code path, then the response
Fix the bug, then make sure the failure is handled. Anything you can predict should become a specific 4xx or 5xx with a helpful body. Anything you cannot predict should still reach a global error handler that logs everything and returns a clean, generic 500.
## Never ship a stack trace
The OWASP cheat sheet warns that unhandled errors "can assist an attacker in this initial phase," and its example shows a raw Java stack trace that revealed the framework and server versions. The goal, in its words, is that "a generic response is returned by the application but the error details are logged server side." Turn off debug modes (Django's `DEBUG`, Flask's debugger, verbose PHP `display_errors`) in production.
```
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain
Traceback (most recent call last):
File "/srv/app/payments.py", line 88, in charge
psycopg2.OperationalError: FATAL: password authentication failed for user "app_prod"
```
```
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json
{"type": "about:blank", "title": "Internal Server Error", "status": 500,
"detail": "Something went wrong on our side. Please try again shortly.",
"instance": "/errors/req_8f2c41"}
```
Why: The first response leaks a file path, a library and a database username. The second uses [RFC 9457 problem details](https://www.rfc-editor.org/rfc/rfc9457) and gives support a reference to look up in the logs.
### A minimal global handler
```
// Express: register last, after all routes
const { randomUUID } = require("node:crypto");
app.use((err, req, res, next) => {
const id = req.get("x-request-id") || randomUUID();
console.error({ id, path: req.path, err }); // full detail, server-side only
res.status(500)
.type("application/problem+json")
.json({ type: "about:blank", title: "Internal Server Error",
status: 500, detail: "Unexpected error.", instance: `/errors/${id}` });
});
```
## 500 and search engines
Google's documentation says that for 500 errors "Google decreases the crawl rate for the site," and that for server errors generally, "already indexed URLs are preserved in the index, but eventually dropped" ([source](https://developers.google.com/search/docs/crawling-indexing/http-network-errors)). A brief outage is recoverable. A template bug that returns 500 on every product page for a week is not something to leave until Monday.
The reverse mistake is just as common: catching the error and rendering an error page with `200 OK`. Google's soft-404 guide lists "a broken connection to the database" as one cause of [soft 404s](https://developers.google.com/search/docs/crawling-indexing/troubleshoot-crawling-errors). An error page should carry an error status.
### If you are a visitor
- Wait a moment and reload once. Transient failures often clear on their own.
- If the error happens only when you submit a form, try simpler input (for example, no emoji or unusual characters in a name field) in case that is triggering the bug.
- Check the service's status page or social accounts for an outage notice.
- If you report it, include the time, the page and any reference ID on the error page. That is what the operators need to find it in their logs.
>
Track your 5xx rate, not just individual errors. A steady trickle of 500s from one endpoint is a bug backlog; a sudden jump across all endpoints is an incident. Both deserve alerts, just not the same kind.
## Frequently asked questions
**What does 500 Internal Server Error mean?**
RFC 9110 defines it as the server having encountered an unexpected condition that prevented it from fulfilling the request. It is the generic catch-all for server-side failures, usually an unhandled exception or a configuration error.
**Is a 500 error my fault as a visitor?**
Almost never. 5xx codes mean the server has erred. Reloading after a short wait sometimes works if the failure was transient, but the fix is up to the site's operators.
**Where do I find the cause of a 500 error?**
In the server-side logs, not the browser. Check your application's log or error tracker first, then the web server or reverse proxy error log (for example nginx's error_log), then the platform logs (systemd journal, container logs, or your host's log viewer).
**Should an API show the error message in a 500 response?**
Show a short generic message and a request or correlation ID, and log the details server-side. OWASP warns that detailed error output, such as stack traces, helps attackers learn about your stack.
**Do 500 errors affect SEO?**
Google says 500 errors make it decrease the crawl rate for a site, and that URLs which persistently return server errors are eventually dropped from the index. Short, rare outages are recoverable; long-running ones are not.
## Sources
1. [RFC 9110 §15.6.1: 500 Internal Server Error](https://www.rfc-editor.org/rfc/rfc9110#name-500-internal-server-error)
2. [RFC 9110 §15.6: Server Error 5xx](https://www.rfc-editor.org/rfc/rfc9110#name-server-error-5xx)
3. [OWASP Error Handling Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet.html)
4. [OWASP: Improper Error Handling](https://owasp.org/www-community/Improper_Error_Handling)
5. [RFC 9457: Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457)
6. [Google Search Central: How HTTP status codes affect Google Search](https://developers.google.com/search/docs/crawling-indexing/http-network-errors)
7. [Google Search Central: Troubleshoot crawling errors](https://developers.google.com/search/docs/crawling-indexing/troubleshoot-crawling-errors)
8. [MDN: 500 Internal Server Error](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500)
---
Source page: https://erroneo.us/developers/http-500-internal-server-error/ · More: https://erroneo.us/llms.txt
==========
---
title: "502 Bad Gateway vs 504 Gateway Timeout (and 503)"
url: https://erroneo.us/developers/http-502-vs-504/
description: "502, 503 and 504 all mean something behind the proxy failed. How to tell them apart, read nginx, Caddy and load balancer logs, and fix the usual causes."
type: guide
section: "Developers"
date_modified: 2026-10-20
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# 502 Bad Gateway vs 504 Gateway Timeout (and 503)
> All three come from the layer in front of your application, which is why the application's own logs are often silent. The code tells you which question to ask: did the backend answer badly, not answer in time, or was it never asked?
Modern sites rarely answer requests directly. A request might pass through a CDN, a load balancer and a reverse proxy such as nginx or Caddy before it reaches the application. When something goes wrong between those layers, the layer in front reports it with a `502`, `503` or `504`. Knowing which layer generated the error, and which of the three it chose, cuts debugging time dramatically.
## The definitions, side by side
| Code | RFC 9110 meaning | Plain English | First suspect |
|---|---|---|---|
| `502` Bad Gateway | "while acting as a gateway or proxy, received an invalid response from an inbound server" ([§15.6.3](https://www.rfc-editor.org/rfc/rfc9110#name-502-bad-gateway)) | I asked the backend and got garbage, or a slammed door | App down, crashed, or listening on the wrong port |
| `503` Service Unavailable | "currently unable to handle the request due to a temporary overload or scheduled maintenance" ([§15.6.4](https://www.rfc-editor.org/rfc/rfc9110#name-503-service-unavailable)) | Not now; try later | Maintenance mode, no healthy backends, load shedding |
| `504` Gateway Timeout | "did not receive a timely response from an upstream server" ([§15.6.5](https://www.rfc-editor.org/rfc/rfc9110#name-504-gateway-timeout)) | I asked the backend and it took too long | Slow query, blocked worker, upstream dependency hanging |
One more detail from RFC 9110: a 503 "MAY send a Retry-After header field," and the spec notes that a server is not obliged to use 503 at all when overloaded: "Some servers might simply refuse the connection." That refused connection, seen from a proxy, often becomes a 502.
## Who generated the error?
Before reading any logs, find out which hop produced the response. The error page and headers usually give it away:
```
curl -sI https://example.com/ | grep -iE "^(HTTP|server|via|cf-ray|x-amz-cf-id|x-cache)"
```
- A `server: cloudflare` header with a `52x` code means Cloudflare could not get a good answer from your origin. Cloudflare's own [5xx guide](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/) lists them: 521 web server down, 522 connection timed out, 524 a timeout occurred, and so on.
- `server: nginx` or `server: Caddy` with a bare error page usually means your own reverse proxy could not reach the app.
- A load balancer error (for example AWS's `awselb`) means the balancer could not reach a healthy target.
## 502 Bad Gateway: common causes
| Cause | Clue | Fix |
|---|---|---|
| Application process not running | Connection refused in the proxy log | Restart it; find out why it died (OOM killer, crash on boot) |
| Proxy pointed at the wrong host, port or socket | 502 on every request since a config change | Check `proxy_pass` / `reverse_proxy` target against what the app listens on |
| App crashed mid-request | "upstream prematurely closed connection" | App log for the crash; often memory or an unhandled signal |
| Keep-alive mismatch | Intermittent 502s under light load | Make the backend's keep-alive timeout longer than the proxy's idle timeout |
| Malformed or oversized response headers | "upstream sent too big header" | Smaller cookies/headers, or raise proxy buffer sizes |
| TLS problem between proxy and backend | Handshake errors in the proxy log | Certificate, SNI or protocol mismatch on the upstream |
| Deploy restarting all instances at once | A burst of 502s every deploy | Rolling restarts, health checks, connection draining |
The keep-alive row deserves emphasis because it is so confusing in practice. AWS's Application Load Balancer documentation lists, among 502 causes, a target that "closed the connection with a TCP RST or a TCP FIN while the load balancer had an outstanding request," and advises: "Check whether the keep-alive duration of the target is shorter than the idle timeout value of the load balancer" ([AWS docs](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html)). The same race exists between nginx and many application servers.
## 504 Gateway Timeout: common causes
| Cause | Clue | Fix |
|---|---|---|
| Slow database query | Only certain pages or filters time out | Query plan, indexes, pagination |
| Worker pool exhausted | Everything slows down together under load | More workers, async I/O, shed load earlier |
| Blocking call to a slow third-party API | Timeouts track the dependency's status page | Client-side timeouts shorter than the proxy's; circuit breakers |
| Long-running job done in the request | Report or export endpoints fail at a round number of seconds | Move to a background job and return `202 Accepted` |
| Network or firewall drops | Timeouts with no load on the app | Security groups, ACLs, routing between proxy and app |
That "round number of seconds" is a useful tell. The defaults are documented: nginx's `proxy_connect_timeout`, `proxy_read_timeout` and `proxy_send_timeout` are each [60 seconds by default](https://nginx.org/en/docs/http/ngx_http_proxy_module.html); Cloudflare's Proxy Read Timeout behind its 524 error is [125 seconds by default](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/); and AWS's ALB lists a 10-second connection timeout among its [504 causes](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html). Caddy is different: its `response_header_timeout` has [no timeout by default](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy), while `dial_timeout` defaults to 3 seconds.
>
nginx's `proxy_read_timeout` is measured "between two successive read operations, not for the transmission of the whole response." A backend that streams a byte every 30 seconds can run for an hour without tripping it; one that thinks silently for 61 seconds will not.
## Reading the proxy's log
When the app log shows nothing, the proxy's error log is where the story is. Typical nginx `error.log` lines and what they mean:
```
connect() failed (111: Connection refused) while connecting to upstream → 502, nothing listening
upstream prematurely closed connection while reading response header → 502, app died or closed early
upstream timed out (110: Connection timed out) while reading response header → 504, app too slow
no live upstreams while connecting to upstream → 502, every backend marked failed
```
```
# nginx
sudo tail -n 100 /var/log/nginx/error.log | grep -i upstream
# Caddy under systemd
journalctl -u caddy --since "15 min ago" | grep -iE "dial|timeout|reverse_proxy"
# Can the proxy host reach the app at all?
curl -sv http://127.0.0.1:8000/health
```
The last command is the quickest test there is. If the proxy host itself cannot get a fast 200 from the app, the problem is not the proxy.
## 503: use it on purpose
503 is the one code in this group you should send deliberately. Google's planned-downtime guidance says that instead of a 404 or an error page with 200, "it's better to return a 503 HTTP result code (Service Unavailable) which tells search engine crawlers that the downtime is temporary," with an optional `Retry-After` ([Google, 2011](https://developers.google.com/search/blog/2011/01/how-to-deal-with-planned-site-downtime)). It also warns that "lasting 503 HTTP result codes can eventually be seen as a sign that the server is now permanently unavailable."
Google's current guide on [pausing a site](https://developers.google.com/search/docs/crawling-indexing/pause-online-business) adds two practical rules: a 503 is for urgently disabling a site for "1-2 days," and you should not "return a 503 HTTP response status code for the robots.txt file because this blocks all crawling."
```
HTTP/1.1 503 Service Unavailable
Retry-After: 1800
Content-Type: text/html; charset=utf-8
Cache-Control: no-store
```
Wrong: ~~Maintenance page served as `200 OK` (or a redirect to `/maintenance`)~~
Right: Maintenance page served as `503` with `Retry-After`, on the original URLs
Why: A 200 tells crawlers and monitors the maintenance page *is* your content. A redirect moves them away from the real URL. A 503 says "same page, come back later."
Wrong: ~~Raising every timeout to 10 minutes to make 504s go away~~
Right: Fix the slow path, set client timeouts shorter than proxy timeouts, move long work to background jobs
Why: Long timeouts keep workers busy waiting, so one slow dependency can exhaust capacity for everything else. Google's SRE book chapter on [cascading failures](https://sre.google/sre-book/addressing-cascading-failures/) describes exactly this pattern and recommends load shedding and deadlines instead.
### If you are a visitor
- Wait a minute and reload. Many 502s happen during a deploy or restart and clear quickly.
- Check the site's status page; these errors often mean a wider outage.
- If only one site fails and every other site works, it is not your connection.
- For a 504 after submitting a form, check whether the action completed (for example, an order confirmation email) before submitting again.
>
Plan for these errors on the client side too. Apps that cache what they can and retry gracefully keep working through brief backend outages; we like the approach in [designing for offline first](https://allthingsn.com/blogs/designing-for-offline-first/). For retry timing, the backoff patterns on the [429 page](https://erroneo.us/developers/http-429-too-many-requests/) apply equally to 502, 503 and 504.
## Frequently asked questions
**What is the difference between 502 and 504?**
Both are sent by a gateway or proxy. 502 Bad Gateway means it received an invalid response from the upstream server (including a refused or reset connection). 504 Gateway Timeout means it did not receive a timely response from upstream.
**What is the difference between 503 and 502?**
503 Service Unavailable means the server is temporarily unable to handle the request because of overload or maintenance, and it may include Retry-After. 502 specifically means a proxy got a bad response from the server behind it.
**Is a 502 or 504 error my fault?**
Almost never. These are server-side problems between the site's proxy or CDN and its application servers. Waiting a minute and reloading is the main thing a visitor can do.
**How do I fix a 504 Gateway Timeout?**
Find out why the upstream is slow (slow queries, blocking calls, an overloaded worker pool) and fix that first. Raising proxy timeouts is sometimes appropriate for genuinely long requests, but long work is usually better moved to a background job that returns 202 Accepted.
**Which code should I use for planned maintenance?**
503 with a Retry-After header, and keep robots.txt available. Google recommends 503 for short planned downtime, warns that long-lasting 503s can lead to URLs being removed, and says not to return 503 for robots.txt because that blocks all crawling.
## Sources
1. [RFC 9110 §15.6.3: 502 Bad Gateway](https://www.rfc-editor.org/rfc/rfc9110#name-502-bad-gateway)
2. [RFC 9110 §15.6.4: 503 Service Unavailable](https://www.rfc-editor.org/rfc/rfc9110#name-503-service-unavailable)
3. [RFC 9110 §15.6.5: 504 Gateway Timeout](https://www.rfc-editor.org/rfc/rfc9110#name-504-gateway-timeout)
4. [RFC 9110 §10.2.3: Retry-After](https://www.rfc-editor.org/rfc/rfc9110#name-retry-after)
5. [nginx: ngx_http_proxy_module (timeouts)](https://nginx.org/en/docs/http/ngx_http_proxy_module.html)
6. [Caddy: reverse_proxy directive](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy)
7. [AWS: Troubleshoot your Application Load Balancers](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html)
8. [Cloudflare: Error 524](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/error-524/)
9. [Cloudflare: Cloudflare 5xx errors](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/)
10. [Google Search Central: Pause or disable a website](https://developers.google.com/search/docs/crawling-indexing/pause-online-business)
11. [Google Search Central: How to deal with planned site downtime (2011)](https://developers.google.com/search/blog/2011/01/how-to-deal-with-planned-site-downtime)
12. [Google SRE Book: Addressing Cascading Failures](https://sre.google/sre-book/addressing-cascading-failures/)
---
Source page: https://erroneo.us/developers/http-502-vs-504/ · More: https://erroneo.us/llms.txt
==========
---
title: "HTTP status codes, explained properly"
url: https://erroneo.us/developers/http-status-codes/
description: "Every HTTP status code from 100 to 511 in plain English: what each means per RFC 9110, the usual cause, and the common mistakes with 401, 404, 429 and 5xx."
type: guide
section: "Developers"
date_modified: 2026-10-22
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# HTTP status codes, explained properly
> A complete, spec-checked reference to every registered HTTP status code, with the common causes behind each one and the codes people most often send by mistake.
Every HTTP response starts with a three-digit number, and that number is a contract. Browsers, caches, load balancers, API clients, uptime monitors and search crawlers all make decisions from it before they read a single byte of the body. The most common HTTP mistake is not an obscure code. It is sending the *wrong* common code: a `200` for an error, a `403` where `401` belongs, a `503` when the problem is really a rate limit.
This page lists every status code in the [IANA HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml), with the meaning as written in [RFC 9110, Section 15](https://www.rfc-editor.org/rfc/rfc9110#name-status-codes) (the June 2022 specification that consolidated HTTP semantics) or the RFC that added the code. The codes that cause the most confusion have their own pages:
- [401 Unauthorized vs 403 Forbidden](https://erroneo.us/developers/http-401-vs-403/)
- [404 Not Found (and 410 Gone, and soft 404s)](https://erroneo.us/developers/http-404-not-found/)
- [429 Too Many Requests](https://erroneo.us/developers/http-429-too-many-requests/)
- [500 Internal Server Error](https://erroneo.us/developers/http-500-internal-server-error/)
- [502 Bad Gateway vs 504 Gateway Timeout (and 503)](https://erroneo.us/developers/http-502-vs-504/)
## Status code explorer
Search every registered code by number (`404`), class (`5xx`) or keyword (“redirect”, “rate limit”). Open a card for the common cause, what to do about it, the defining spec, and a curl one-liner to check the status yourself. The full tables, with the same data, follow below.
-
** 100 Continue The start of the request was received and not rejected; send the rest Where you see it:** Large uploads sent with `Expect: 100-continue`
**What should I do?** Nothing to do: it is an interim response. A client that sent Expect: 100-continue should go ahead and send the rest of the request body.
**Defined in:** [RFC 9110 §15.2.1](https://www.rfc-editor.org/rfc/rfc9110#name-100-continue)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 100
```
-
** 101 Switching Protocols The server agrees to change protocol via the `Upgrade` header Where you see it:** WebSocket handshakes
**What should I do?** Nothing to do: the server agreed to change protocol via the Upgrade header, as in a WebSocket handshake. The rest of the conversation uses the new protocol.
**Defined in:** [RFC 9110 §15.2.2](https://www.rfc-editor.org/rfc/rfc9110#name-101-switching-protocols)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 101
```
-
** 102 Processing WebDAV interim response for long operations Where you see it:** Rare outside WebDAV
**What should I do?** Nothing to do: it is a WebDAV interim response for a long operation. Keep waiting for the final status code.
**Defined in:** [RFC 2518 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 102
```
-
** 103 Early Hints Headers (usually `Link: rel=preload`) the final response is likely to include Where you see it:** CDNs letting browsers preload CSS and fonts while the page renders
**What should I do?** Nothing to do: these are early hints, usually Link: rel=preload headers that let the browser start fetching CSS and fonts. The final response still follows.
**Defined in:** [RFC 8297](https://www.rfc-editor.org/rfc/rfc8297)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 103
```
-
** 200 OK The request succeeded; the body depends on the method Typical use:** A page or API result
**What should I do?** Success. If you run the server, never send 200 for an error: retries, caches, alerting and crawlers read the status line, not your JSON. Return the matching 4xx or 5xx with the details in the body.
**Defined in:** [§15.3.1](https://www.rfc-editor.org/rfc/rfc9110#name-200-ok)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 200
```
-
** 201 Created One or more new resources were created, identified by `Location` or the target URI Typical use:** Successful `POST` that creates a record
**What should I do?** The resource was created. Look at the Location header (or the target URI) to find the new resource.
**Defined in:** [§15.3.2](https://www.rfc-editor.org/rfc/rfc9110#name-201-created)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 201
```
-
** 202 Accepted Accepted for processing, not finished; "intentionally noncommittal" Typical use:** Queued jobs, async exports
**What should I do?** Accepted but not finished: the work is queued. Check the job's status later rather than assuming it succeeded; the code is intentionally noncommittal.
**Defined in:** [§15.3.3](https://www.rfc-editor.org/rfc/rfc9110#name-202-accepted)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 202
```
-
** 203 Non-Authoritative Information Success, but a transforming proxy modified the content Typical use:** Rare
**What should I do?** The request succeeded, but a transforming proxy modified the content. If the body looks different from what the origin sent, look at the proxy.
**Defined in:** [§15.3.4](https://www.rfc-editor.org/rfc/rfc9110#name-203-non-authoritative-infor)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 203
```
-
** 204 No Content Success with nothing to send back Typical use:** `DELETE`, or a `PUT` that returns no body
**What should I do?** Success with no body. Don't call JSON.parse or response.json() on it: an empty body throws 'Unexpected end of JSON input'.
**Defined in:** [§15.3.5](https://www.rfc-editor.org/rfc/rfc9110#name-204-no-content)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 204
```
-
** 205 Reset Content Success; the client should reset the document view (for example, clear a form) Typical use:** Rare
**What should I do?** Success: the client should reset the document view, for example by clearing the form that was just submitted.
**Defined in:** [§15.3.6](https://www.rfc-editor.org/rfc/rfc9110#name-205-reset-content)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 205
```
-
** 206 Partial Content Only the requested byte ranges are being sent Typical use:** Video seeking, resumable downloads
**What should I do?** Only the requested byte ranges were sent, as in video seeking or a resumed download. If you expected the whole file, check the Range header your client sent.
**Defined in:** [§15.3.7](https://www.rfc-editor.org/rfc/rfc9110#name-206-partial-content)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 206
```
-
** 207 Multi-Status Several status values for several resources, in an XML body Typical use:** WebDAV
**What should I do?** WebDAV: the XML body holds a separate status for each resource. Read each one, because some may have failed even though the response as a whole is 207.
**Defined in:** [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 207
```
-
** 208 Already Reported WebDAV binding members already listed earlier in the response Typical use:** WebDAV
**What should I do?** WebDAV: these binding members were already listed earlier in the response, so they are not repeated. Nothing to fix.
**Defined in:** [RFC 5842 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 208
```
-
** 226 IM Used Response is the result of instance manipulations (delta encoding) Typical use:** Very rare
**What should I do?** The response is the result of instance manipulations such as delta encoding. You will rarely see it; if you do, your client asked for it.
**Defined in:** [RFC 3229 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 226
```
-
** 300 Multiple Choices Several representations exist; the client may pick one Method preserved?:** n/a
**What should I do?** Several representations exist and the client may pick one. Choose a specific representation and request it directly.
**Defined in:** [§15.4.1](https://www.rfc-editor.org/rfc/rfc9110#name-300-multiple-choices)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 300
```
-
** 301 Moved Permanently New permanent URI; future requests should use it Method preserved?:** Clients *may* change POST to GET
**What should I do?** The resource moved for good: update your links and bookmarks to the new URI in Location. Clients may change a POST into a GET when following it; use 308 if the method must be kept.
**Defined in:** [§15.4.2](https://www.rfc-editor.org/rfc/rfc9110#name-301-moved-permanently)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 301
```
-
** 302 Found Temporarily at a different URI; keep using the original Method preserved?:** Clients *may* change POST to GET
**What should I do?** A temporary move: keep using the original URL. If you run the site and the page has moved for good, send 301 or 308 instead, which Google treats as strong canonical signals.
**Defined in:** [§15.4.3](https://www.rfc-editor.org/rfc/rfc9110#name-302-found)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 302
```
-
** 303 See Other Go and GET a different resource as the answer Method preserved?:** No: becomes GET by design
**What should I do?** Go and GET the resource in Location as the answer; the method becomes GET by design, whatever the original request used.
**Defined in:** [§15.4.4](https://www.rfc-editor.org/rfc/rfc9110#name-303-see-other)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 303
```
-
** 304 Not Modified A conditional GET found the cached copy still valid Method preserved?:** n/a
**What should I do?** Your conditional GET found the cached copy still valid, so use the copy you already have.
**Defined in:** [§15.4.5](https://www.rfc-editor.org/rfc/rfc9110#name-304-not-modified)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 304
```
-
** 305 Use Proxy Deprecated Method preserved?:** n/a
**What should I do?** Use Proxy is deprecated. Don't send it, and don't rely on clients honoring it.
**Defined in:** [§15.4.6](https://www.rfc-editor.org/rfc/rfc9110#name-305-use-proxy)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 305
```
-
** 306 (Unused) Reserved; no longer used Method preserved?:** n/a
**What should I do?** Reserved and no longer used. If a server sends it, treat it like any unknown 3xx and report it to the operator.
**Defined in:** [§15.4.7](https://www.rfc-editor.org/rfc/rfc9110#name-306-unused)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 306
```
-
** 307 Temporary Redirect Temporary, and the client MUST NOT change the method Method preserved?:** Yes
**What should I do?** A temporary redirect where the client must not change the method. Repeat the same request, with the same method and body, at the Location URL.
**Defined in:** [§15.4.8](https://www.rfc-editor.org/rfc/rfc9110#name-307-temporary-redirect)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 307
```
-
** 308 Permanent Redirect Permanent, like 301, but without the method change Method preserved?:** Yes
**What should I do?** A permanent redirect that keeps the method and body. Update your links, and use 308 instead of 301 when a POST must stay a POST.
**Defined in:** [§15.4.9](https://www.rfc-editor.org/rfc/rfc9110#name-308-permanent-redirect)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 308
```
-
** 400 Bad Request The server cannot or will not process a request it perceives as a client error Common cause:** Malformed JSON, bad query parameters, oversized cookies
**What should I do?** The server perceived a client error. Check for malformed JSON, bad query parameters or oversized cookies, fix the request, then try again; repeating the identical request is pointless.
**Defined in:** [§15.5.1](https://www.rfc-editor.org/rfc/rfc9110#name-400-bad-request)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 400
```
-
** 401 Unauthorized No valid authentication credentials; MUST include `WWW-Authenticate` Common cause:** Missing or expired token
**What should I do?** No valid credentials: log in again or refresh your token, then retry. If you run the server, always include a WWW-Authenticate challenge, which RFC 9110 requires. [Full guide →](https://erroneo.us/developers/http-401-vs-403/)
**Defined in:** [§15.5.2](https://www.rfc-editor.org/rfc/rfc9110#name-401-unauthorized)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 401
```
-
** 402 Payment Required Reserved for future use Common cause:** Some APIs use it informally for billing problems
**What should I do?** Reserved for future use. Some APIs use it informally for billing problems, so check your account's billing status in that API's dashboard.
**Defined in:** [§15.5.3](https://www.rfc-editor.org/rfc/rfc9110#name-402-payment-required)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 402
```
-
** 403 Forbidden Understood, but refused; credentials will not help Common cause:** Logged in without permission, IP or WAF block, file permissions
**What should I do?** The server understood but refuses, and logging in again will not help. Check you are signed in with the right account; operators should look at roles, scopes, WAF or IP rules and file permissions. [Full guide →](https://erroneo.us/developers/http-401-vs-403/)
**Defined in:** [§15.5.4](https://www.rfc-editor.org/rfc/rfc9110#name-403-forbidden)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 403
```
-
** 404 Not Found No current representation, or the server will not say whether one exists Common cause:** Typos, deleted pages, broken links, wrong routes
**What should I do?** Nothing at that address. Check the URL for typos, trim the path from the right, or search the site. If you run it, add 301s for moved pages and make sure your error page really returns 404, not 200. [Full guide →](https://erroneo.us/developers/http-404-not-found/)
**Defined in:** [§15.5.5](https://www.rfc-editor.org/rfc/rfc9110#name-404-not-found)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 404
```
-
** 405 Method Not Allowed Method known but not supported here; MUST include `Allow` Common cause:** POST to a GET-only route
**What should I do?** The method isn't supported on this URL. Check the Allow header in the response for the methods that are, for example a POST sent to a GET-only route.
**Defined in:** [§15.5.6](https://www.rfc-editor.org/rfc/rfc9110#name-405-method-not-allowed)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 405
```
-
** 406 Not Acceptable Nothing matches the client's `Accept*` headers Common cause:** Strict content negotiation
**What should I do?** Nothing matches the Accept headers your client sent. Loosen or correct the Accept header, or ask for a format the server offers.
**Defined in:** [§15.5.7](https://www.rfc-editor.org/rfc/rfc9110#name-406-not-acceptable)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 406
```
-
** 407 Proxy Authentication Required Like 401, but for a proxy Common cause:** Corporate proxies
**What should I do?** Like 401, but for a proxy: authenticate with the proxy, often a corporate one, before retrying.
**Defined in:** [§15.5.8](https://www.rfc-editor.org/rfc/rfc9110#name-407-proxy-authentication-re)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 407
```
-
** 408 Request Timeout The full request did not arrive in time Common cause:** Slow uploads, idle keep-alive connections
**What should I do?** The full request did not arrive in time. Retry, and for slow uploads check your connection; idle keep-alive connections can also trigger it.
**Defined in:** [§15.5.9](https://www.rfc-editor.org/rfc/rfc9110#name-408-request-timeout)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 408
```
-
** 409 Conflict Conflicts with the current state of the resource Common cause:** Edit conflicts, duplicate unique keys
**What should I do?** The request conflicts with the current state of the resource, such as an edit conflict or a duplicate unique key. Fetch the latest version, resolve the conflict, then resend.
**Defined in:** [§15.5.10](https://www.rfc-editor.org/rfc/rfc9110#name-409-conflict)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 409
```
-
** 410 Gone No longer available, and likely permanent Common cause:** Deliberately retired pages or promotions
**What should I do?** The resource was removed on purpose and is likely gone for good. Remove links to it. If you run the site, use 410 only for deliberate removals with no replacement. [Full guide →](https://erroneo.us/developers/http-404-not-found/)
**Defined in:** [§15.5.11](https://www.rfc-editor.org/rfc/rfc9110#name-410-gone)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 410
```
-
** 411 Length Required A `Content-Length` is required Common cause:** Clients streaming without length
**What should I do?** The server requires a Content-Length header. Send the request with its length instead of streaming it without one.
**Defined in:** [§15.5.12](https://www.rfc-editor.org/rfc/rfc9110#name-411-length-required)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 411
```
-
** 412 Precondition Failed A conditional header such as `If-Match` evaluated false Common cause:** Optimistic concurrency with ETags
**What should I do?** A conditional header such as If-Match evaluated false: someone changed the resource since you fetched it. Fetch it again, reapply your change and retry with the new ETag.
**Defined in:** [§15.5.13](https://www.rfc-editor.org/rfc/rfc9110#name-412-precondition-failed)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 412
```
-
** 413 Content Too Large The request body is larger than the server will process Common cause:** Upload limits such as nginx `client_max_body_size`
**What should I do?** The request body is larger than the server will process. Send a smaller body; operators can raise upload limits such as nginx client_max_body_size if appropriate.
**Defined in:** [§15.5.14](https://www.rfc-editor.org/rfc/rfc9110#name-413-content-too-large)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 413
```
-
** 414 URI Too Long The target URI is longer than the server will interpret Common cause:** A POST converted into a GET with a huge query string; redirect loops
**What should I do?** The URI is too long for the server. Move large data out of the query string into a POST body, and check for redirect loops that keep growing the URL.
**Defined in:** [§15.5.15](https://www.rfc-editor.org/rfc/rfc9110#name-414-uri-too-long)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 414
```
-
** 415 Unsupported Media Type The body's format is not supported Common cause:** Sending form data to a JSON-only endpoint
**What should I do?** The server doesn't support the body's format. Send the format it expects and set Content-Type to match, for example JSON instead of form data.
**Defined in:** [§15.5.16](https://www.rfc-editor.org/rfc/rfc9110#name-415-unsupported-media-type)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 415
```
-
** 416 Range Not Satisfiable The requested byte ranges cannot be served Common cause:** Resuming a download past the end of a file
**What should I do?** The requested byte range can't be served, for example when resuming a download past the end of the file. Check the range you asked for against the file's size.
**Defined in:** [§15.5.17](https://www.rfc-editor.org/rfc/rfc9110#name-416-range-not-satisfiable)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 416
```
-
** 417 Expectation Failed The `Expect` header could not be met Common cause:** Proxies that do not support 100-continue
**What should I do?** The Expect header could not be met, often by a proxy that does not support 100-continue. Send the request without Expect: 100-continue.
**Defined in:** [§15.5.18](https://www.rfc-editor.org/rfc/rfc9110#name-417-expectation-failed)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 417
```
-
** 418 (Unused) Reserved; originally the "I'm a teapot" joke Common cause:** Easter eggs [Meet the teapot →](https://erroneo.us/developers/http-418-im-a-teapot/)
**What should I do?** Reserved: it began as the 'I'm a teapot' joke in RFC 2324. Treat it as an Easter egg, and don't use it to mean anything in a real API.
**Defined in:** [§15.5.19](https://www.rfc-editor.org/rfc/rfc9110#name-418-unused)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 418
```
-
** 421 Misdirected Request This server cannot answer authoritatively for that URI Common cause:** HTTP/2 connection reuse across hostnames with different certificates
**What should I do?** This server can't answer authoritatively for that URI, often after HTTP/2 connection reuse across hostnames with different certificates. Make sure the request goes over a connection to the right host.
**Defined in:** [§15.5.20](https://www.rfc-editor.org/rfc/rfc9110#name-421-misdirected-request)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 421
```
-
** 422 Unprocessable Content Syntax is fine, but the instructions cannot be processed Common cause:** Validation failures on well-formed JSON
**What should I do?** The syntax is fine but the content failed validation. Read the error body for the field that failed, fix the value, then resend.
**Defined in:** [§15.5.21](https://www.rfc-editor.org/rfc/rfc9110#name-422-unprocessable-content)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 422
```
-
** 423 Locked The resource is locked Common cause:** WebDAV
**What should I do?** WebDAV: the resource is locked. Wait for the lock to be released, or release it if you hold it, then retry.
**Defined in:** [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 423
```
-
** 424 Failed Dependency Failed because an earlier action failed Common cause:** WebDAV
**What should I do?** WebDAV: this action failed because an earlier action it depended on failed. Fix the earlier failure first.
**Defined in:** [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 424
```
-
** 425 Too Early The server will not risk processing a possibly replayed request Common cause:** TLS 1.3 early data (0-RTT)
**What should I do?** The server won't risk processing a request that might be replayed, as with TLS 1.3 early data (0-RTT). Retry after the handshake completes.
**Defined in:** [RFC 8470](https://www.rfc-editor.org/rfc/rfc8470)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 425
```
-
** 426 Upgrade Required Refused on this protocol; MUST send `Upgrade` Common cause:** Services requiring a newer protocol
**What should I do?** Refused on this protocol. Check the Upgrade header in the response and switch to the protocol it names.
**Defined in:** [§15.5.22](https://www.rfc-editor.org/rfc/rfc9110#name-426-upgrade-required)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 426
```
-
** 428 Precondition Required The server requires the request to be conditional Common cause:** Preventing lost updates; require `If-Match`
**What should I do?** The server requires a conditional request to prevent lost updates. Fetch the resource, then resend your change with If-Match and its ETag.
**Defined in:** [RFC 6585 §3](https://www.rfc-editor.org/rfc/rfc6585#section-3)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 428
```
-
** 429 Too Many Requests Too many requests in a given time (rate limiting) Common cause:** API quotas, login throttling, scrapers
**What should I do?** You hit a rate limit. Stop retrying immediately: honor Retry-After, otherwise back off exponentially with jitter. If you run the server, return 429 (not 503) for per-client limits and send Retry-After. [Full guide →](https://erroneo.us/developers/http-429-too-many-requests/)
**Defined in:** [RFC 6585 §4](https://www.rfc-editor.org/rfc/rfc6585#section-4)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 429
```
-
** 431 Request Header Fields Too Large Headers, in total or one of them, are too large Common cause:** Bloated cookies
**What should I do?** The request headers, in total or one of them, are too large. Bloated cookies are the common cause, so clearing the site's cookies is the first thing to try.
**Defined in:** [RFC 6585 §5](https://www.rfc-editor.org/rfc/rfc6585#section-5)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 431
```
-
** 451 Unavailable For Legal Reasons Access denied as a consequence of a legal demand Common cause:** Court orders, regional legal blocks
**What should I do?** Access was denied as a consequence of a legal demand, such as a court order or a regional legal block. There is nothing to fix in the request itself.
**Defined in:** [RFC 7725 §3](https://www.rfc-editor.org/rfc/rfc7725#section-3)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 451
```
-
** 500 Internal Server Error An unexpected condition prevented fulfilling the request Common cause:** Unhandled exceptions, bad config, failed deploys
**What should I do?** The server hit an unexpected condition. Visitors can wait a moment and reload once. Operators should check the application log for the stack trace and ask what changed: a deploy, config, dependency or credential. [Full guide →](https://erroneo.us/developers/http-500-internal-server-error/)
**Defined in:** [§15.6.1](https://www.rfc-editor.org/rfc/rfc9110#name-500-internal-server-error)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 500
```
-
** 501 Not Implemented The server does not support the required functionality Common cause:** Unrecognised method
**What should I do?** The server doesn't support the functionality required, typically an unrecognised method. Use a method the server supports.
**Defined in:** [§15.6.2](https://www.rfc-editor.org/rfc/rfc9110#name-501-not-implemented)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 501
```
-
** 502 Bad Gateway A gateway or proxy got an invalid response from upstream Common cause:** App crashed, connection refused, upstream reset
**What should I do?** A gateway or proxy got an invalid response from upstream. Visitors can wait a minute and reload. Operators should check whether the app is running and listening where the proxy points, and read the proxy's error log. [Full guide →](https://erroneo.us/developers/http-502-vs-504/)
**Defined in:** [§15.6.3](https://www.rfc-editor.org/rfc/rfc9110#name-502-bad-gateway)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 502
```
-
** 503 Service Unavailable Temporary overload or maintenance; may send `Retry-After` Common cause:** Deploys, maintenance mode, load shedding
**What should I do?** The service is temporarily overloaded or in maintenance. Wait and retry, honoring Retry-After if present. Operators should send 503 deliberately for maintenance and use 429, not 503, for per-client rate limits. [Full guide →](https://erroneo.us/developers/http-502-vs-504/)
**Defined in:** [§15.6.4](https://www.rfc-editor.org/rfc/rfc9110#name-503-service-unavailable)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 503
```
-
** 504 Gateway Timeout A gateway or proxy did not get a timely response from upstream Common cause:** Slow queries, long-running requests
**What should I do?** A gateway or proxy didn't get a timely response from upstream. Before resubmitting a form, check whether the action completed. Operators should fix the slow path rather than raising every timeout. [Full guide →](https://erroneo.us/developers/http-502-vs-504/)
**Defined in:** [§15.6.5](https://www.rfc-editor.org/rfc/rfc9110#name-504-gateway-timeout)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 504
```
-
** 505 HTTP Version Not Supported The major HTTP version is not supported Common cause:** Very old or very unusual clients
**What should I do?** The server doesn't support the major HTTP version used. Retry with a common HTTP version; this mostly affects very old or unusual clients.
**Defined in:** [§15.6.6](https://www.rfc-editor.org/rfc/rfc9110#name-505-http-version-not-suppor)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 505
```
-
** 506 Variant Also Negotiates Content negotiation configuration error Common cause:** Rare
**What should I do?** A content negotiation configuration error on the server. Nothing to fix in your request; report it to the site's operator.
**Defined in:** [RFC 2295 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 506
```
-
** 507 Insufficient Storage The server cannot store what is needed to complete the request Common cause:** WebDAV, full disks
**What should I do?** The server can't store what it needs to complete the request, as with a full disk. Operators should free or add storage; clients can retry later.
**Defined in:** [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 507
```
-
** 508 Loop Detected An infinite loop was found while processing Common cause:** WebDAV bindings
**What should I do?** WebDAV: the server found an infinite loop while processing, typically from bindings. Operators should check the binding configuration.
**Defined in:** [RFC 5842 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 508
```
-
** 510 Not Extended Marked obsoleted in the registry Common cause:** Do not use
**What should I do?** Marked obsoleted in the IANA registry. Do not use it.
**Defined in:** [RFC 2774 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 510
```
-
** 511 Network Authentication Required The client must authenticate to gain network access Common cause:** Captive portals on hotel and airport Wi-Fi
**What should I do?** You need to authenticate to get network access, as on hotel and airport Wi-Fi captive portals. Open any web page in a browser to reach the sign-in screen.
**Defined in:** [RFC 6585 §6](https://www.rfc-editor.org/rfc/rfc6585#section-6)
```
curl -sI https://example.com/your/path | head -n 1
# look for: HTTP/… 511
```
## How the five classes work
RFC 9110 says the first digit defines the class of response, and that a client which does not recognise a specific code [must treat it as the `x00` code of its class](https://www.rfc-editor.org/rfc/rfc9110#name-status-codes). An unknown `471` is handled like `400`; an unknown `599` like `500`. That rule is why picking the right class matters more than picking a clever specific code.
| Class | Meaning in RFC 9110 | Who probably needs to act |
|---|---|---|
| `1xx` | Informational: an interim response before the final one | Nobody; the client keeps waiting |
| `2xx` | Successful: the request was received, understood and accepted | Nobody |
| `3xx` | Redirection: further action is needed to complete the request | The client follows the `Location` |
| `4xx` | Client error: the client "seems to have erred" | The caller must change the request |
| `5xx` | Server error: the server "is aware that it has erred or is incapable of performing the requested method" | The operator of the server |
## 1xx Informational
| Code | Name | What it means | Where you see it | Spec |
|---|---|---|---|---|
| `100` | Continue | The start of the request was received and not rejected; send the rest | Large uploads sent with `Expect: 100-continue` | [RFC 9110 §15.2.1](https://www.rfc-editor.org/rfc/rfc9110#name-100-continue) |
| `101` | Switching Protocols | The server agrees to change protocol via the `Upgrade` header | WebSocket handshakes | [RFC 9110 §15.2.2](https://www.rfc-editor.org/rfc/rfc9110#name-101-switching-protocols) |
| `102` | Processing | WebDAV interim response for long operations | Rare outside WebDAV | [RFC 2518 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) |
| `103` | Early Hints | Headers (usually `Link: rel=preload`) the final response is likely to include | CDNs letting browsers preload CSS and fonts while the page renders | [RFC 8297](https://www.rfc-editor.org/rfc/rfc8297) |
## 2xx Successful
| Code | Name | What it means | Typical use | Spec |
|---|---|---|---|---|
| `200` | OK | The request succeeded; the body depends on the method | A page or API result | [§15.3.1](https://www.rfc-editor.org/rfc/rfc9110#name-200-ok) |
| `201` | Created | One or more new resources were created, identified by `Location` or the target URI | Successful `POST` that creates a record | [§15.3.2](https://www.rfc-editor.org/rfc/rfc9110#name-201-created) |
| `202` | Accepted | Accepted for processing, not finished; "intentionally noncommittal" | Queued jobs, async exports | [§15.3.3](https://www.rfc-editor.org/rfc/rfc9110#name-202-accepted) |
| `203` | Non-Authoritative Information | Success, but a transforming proxy modified the content | Rare | [§15.3.4](https://www.rfc-editor.org/rfc/rfc9110#name-203-non-authoritative-infor) |
| `204` | No Content | Success with nothing to send back | `DELETE`, or a `PUT` that returns no body | [§15.3.5](https://www.rfc-editor.org/rfc/rfc9110#name-204-no-content) |
| `205` | Reset Content | Success; the client should reset the document view (for example, clear a form) | Rare | [§15.3.6](https://www.rfc-editor.org/rfc/rfc9110#name-205-reset-content) |
| `206` | Partial Content | Only the requested byte ranges are being sent | Video seeking, resumable downloads | [§15.3.7](https://www.rfc-editor.org/rfc/rfc9110#name-206-partial-content) |
| `207` | Multi-Status | Several status values for several resources, in an XML body | WebDAV | [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918) |
| `208` | Already Reported | WebDAV binding members already listed earlier in the response | WebDAV | [RFC 5842 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) |
| `226` | IM Used | Response is the result of instance manipulations (delta encoding) | Very rare | [RFC 3229 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) |
Wrong: ~~`HTTP/1.1 200 OK` with `{"success": false, "error": "User not found"}`~~
Right: `HTTP/1.1 404 Not Found` with `Content-Type: application/problem+json` and the details in the body
Why: Retries, caches, alerting and crawlers read the status line, not your JSON. A 200 tells all of them that the request worked. [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457) defines a standard error body so you do not have to invent one.
## 3xx Redirection
| Code | Name | What it means | Method preserved? | Spec |
|---|---|---|---|---|
| `300` | Multiple Choices | Several representations exist; the client may pick one | n/a | [§15.4.1](https://www.rfc-editor.org/rfc/rfc9110#name-300-multiple-choices) |
| `301` | Moved Permanently | New permanent URI; future requests should use it | Clients *may* change POST to GET | [§15.4.2](https://www.rfc-editor.org/rfc/rfc9110#name-301-moved-permanently) |
| `302` | Found | Temporarily at a different URI; keep using the original | Clients *may* change POST to GET | [§15.4.3](https://www.rfc-editor.org/rfc/rfc9110#name-302-found) |
| `303` | See Other | Go and GET a different resource as the answer | No: becomes GET by design | [§15.4.4](https://www.rfc-editor.org/rfc/rfc9110#name-303-see-other) |
| `304` | Not Modified | A conditional GET found the cached copy still valid | n/a | [§15.4.5](https://www.rfc-editor.org/rfc/rfc9110#name-304-not-modified) |
| `305` | Use Proxy | Deprecated | n/a | [§15.4.6](https://www.rfc-editor.org/rfc/rfc9110#name-305-use-proxy) |
| `306` | (Unused) | Reserved; no longer used | n/a | [§15.4.7](https://www.rfc-editor.org/rfc/rfc9110#name-306-unused) |
| `307` | Temporary Redirect | Temporary, and the client MUST NOT change the method | Yes | [§15.4.8](https://www.rfc-editor.org/rfc/rfc9110#name-307-temporary-redirect) |
| `308` | Permanent Redirect | Permanent, like 301, but without the method change | Yes | [§15.4.9](https://www.rfc-editor.org/rfc/rfc9110#name-308-permanent-redirect) |
The usual mistake is reaching for `302` by habit. If a page has moved for good, send `301` or `308`. Google's documentation says it treats [301 and 308 as strong signals](https://developers.google.com/search/docs/crawling-indexing/http-network-errors) that the target should be canonical, and 302, 303 and 307 as weak signals. Google's crawlers follow up to 10 redirect hops by default, so long chains waste crawling and can break.
## 4xx Client errors
Per [RFC 9110 §15.5](https://www.rfc-editor.org/rfc/rfc9110#name-client-error-4xx), a 4xx response should carry an explanation of the error and say whether it is temporary or permanent. The caller has to change something before trying again; repeating the identical request is usually pointless (429 is the exception: wait, then retry).
| Code | Name | What it means | Common cause | Spec |
|---|---|---|---|---|
| `400` | Bad Request | The server cannot or will not process a request it perceives as a client error | Malformed JSON, bad query parameters, oversized cookies | [§15.5.1](https://www.rfc-editor.org/rfc/rfc9110#name-400-bad-request) |
| `401` | Unauthorized | No valid authentication credentials; MUST include `WWW-Authenticate` | Missing or expired token | [§15.5.2](https://www.rfc-editor.org/rfc/rfc9110#name-401-unauthorized) |
| `402` | Payment Required | Reserved for future use | Some APIs use it informally for billing problems | [§15.5.3](https://www.rfc-editor.org/rfc/rfc9110#name-402-payment-required) |
| `403` | Forbidden | Understood, but refused; credentials will not help | Logged in without permission, IP or WAF block, file permissions | [§15.5.4](https://www.rfc-editor.org/rfc/rfc9110#name-403-forbidden) |
| `404` | Not Found | No current representation, or the server will not say whether one exists | Typos, deleted pages, broken links, wrong routes | [§15.5.5](https://www.rfc-editor.org/rfc/rfc9110#name-404-not-found) |
| `405` | Method Not Allowed | Method known but not supported here; MUST include `Allow` | POST to a GET-only route | [§15.5.6](https://www.rfc-editor.org/rfc/rfc9110#name-405-method-not-allowed) |
| `406` | Not Acceptable | Nothing matches the client's `Accept*` headers | Strict content negotiation | [§15.5.7](https://www.rfc-editor.org/rfc/rfc9110#name-406-not-acceptable) |
| `407` | Proxy Authentication Required | Like 401, but for a proxy | Corporate proxies | [§15.5.8](https://www.rfc-editor.org/rfc/rfc9110#name-407-proxy-authentication-re) |
| `408` | Request Timeout | The full request did not arrive in time | Slow uploads, idle keep-alive connections | [§15.5.9](https://www.rfc-editor.org/rfc/rfc9110#name-408-request-timeout) |
| `409` | Conflict | Conflicts with the current state of the resource | Edit conflicts, duplicate unique keys | [§15.5.10](https://www.rfc-editor.org/rfc/rfc9110#name-409-conflict) |
| `410` | Gone | No longer available, and likely permanent | Deliberately retired pages or promotions | [§15.5.11](https://www.rfc-editor.org/rfc/rfc9110#name-410-gone) |
| `411` | Length Required | A `Content-Length` is required | Clients streaming without length | [§15.5.12](https://www.rfc-editor.org/rfc/rfc9110#name-411-length-required) |
| `412` | Precondition Failed | A conditional header such as `If-Match` evaluated false | Optimistic concurrency with ETags | [§15.5.13](https://www.rfc-editor.org/rfc/rfc9110#name-412-precondition-failed) |
| `413` | Content Too Large | The request body is larger than the server will process | Upload limits such as nginx `client_max_body_size` | [§15.5.14](https://www.rfc-editor.org/rfc/rfc9110#name-413-content-too-large) |
| `414` | URI Too Long | The target URI is longer than the server will interpret | A POST converted into a GET with a huge query string; redirect loops | [§15.5.15](https://www.rfc-editor.org/rfc/rfc9110#name-414-uri-too-long) |
| `415` | Unsupported Media Type | The body's format is not supported | Sending form data to a JSON-only endpoint | [§15.5.16](https://www.rfc-editor.org/rfc/rfc9110#name-415-unsupported-media-type) |
| `416` | Range Not Satisfiable | The requested byte ranges cannot be served | Resuming a download past the end of a file | [§15.5.17](https://www.rfc-editor.org/rfc/rfc9110#name-416-range-not-satisfiable) |
| `417` | Expectation Failed | The `Expect` header could not be met | Proxies that do not support 100-continue | [§15.5.18](https://www.rfc-editor.org/rfc/rfc9110#name-417-expectation-failed) |
| `418` | (Unused) | Reserved; originally the "I'm a teapot" joke | Easter eggs | [§15.5.19](https://www.rfc-editor.org/rfc/rfc9110#name-418-unused) |
| `421` | Misdirected Request | This server cannot answer authoritatively for that URI | HTTP/2 connection reuse across hostnames with different certificates | [§15.5.20](https://www.rfc-editor.org/rfc/rfc9110#name-421-misdirected-request) |
| `422` | Unprocessable Content | Syntax is fine, but the instructions cannot be processed | Validation failures on well-formed JSON | [§15.5.21](https://www.rfc-editor.org/rfc/rfc9110#name-422-unprocessable-content) |
| `423` | Locked | The resource is locked | WebDAV | [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918) |
| `424` | Failed Dependency | Failed because an earlier action failed | WebDAV | [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918) |
| `425` | Too Early | The server will not risk processing a possibly replayed request | TLS 1.3 early data (0-RTT) | [RFC 8470](https://www.rfc-editor.org/rfc/rfc8470) |
| `426` | Upgrade Required | Refused on this protocol; MUST send `Upgrade` | Services requiring a newer protocol | [§15.5.22](https://www.rfc-editor.org/rfc/rfc9110#name-426-upgrade-required) |
| `428` | Precondition Required | The server requires the request to be conditional | Preventing lost updates; require `If-Match` | [RFC 6585 §3](https://www.rfc-editor.org/rfc/rfc6585#section-3) |
| `429` | Too Many Requests | Too many requests in a given time (rate limiting) | API quotas, login throttling, scrapers | [RFC 6585 §4](https://www.rfc-editor.org/rfc/rfc6585#section-4) |
| `431` | Request Header Fields Too Large | Headers, in total or one of them, are too large | Bloated cookies | [RFC 6585 §5](https://www.rfc-editor.org/rfc/rfc6585#section-5) |
| `451` | Unavailable For Legal Reasons | Access denied as a consequence of a legal demand | Court orders, regional legal blocks | [RFC 7725 §3](https://www.rfc-editor.org/rfc/rfc7725#section-3) |
>
**About 418.** [RFC 2324](https://www.rfc-editor.org/rfc/rfc2324) was published on 1 April 1998 as a parody. RFC 9110 explains that the code "has been deployed as a joke often enough for the code to be unusable for any future use," so it is [reserved in the registry](https://www.rfc-editor.org/rfc/rfc9110#name-418-unused) rather than assigned. The whole story, with an animated teapot, is on our [418 I’m a teapot](https://erroneo.us/developers/http-418-im-a-teapot/) page.
## 5xx Server errors
| Code | Name | What it means | Common cause | Spec |
|---|---|---|---|---|
| `500` | Internal Server Error | An unexpected condition prevented fulfilling the request | Unhandled exceptions, bad config, failed deploys | [§15.6.1](https://www.rfc-editor.org/rfc/rfc9110#name-500-internal-server-error) |
| `501` | Not Implemented | The server does not support the required functionality | Unrecognised method | [§15.6.2](https://www.rfc-editor.org/rfc/rfc9110#name-501-not-implemented) |
| `502` | Bad Gateway | A gateway or proxy got an invalid response from upstream | App crashed, connection refused, upstream reset | [§15.6.3](https://www.rfc-editor.org/rfc/rfc9110#name-502-bad-gateway) |
| `503` | Service Unavailable | Temporary overload or maintenance; may send `Retry-After` | Deploys, maintenance mode, load shedding | [§15.6.4](https://www.rfc-editor.org/rfc/rfc9110#name-503-service-unavailable) |
| `504` | Gateway Timeout | A gateway or proxy did not get a timely response from upstream | Slow queries, long-running requests | [§15.6.5](https://www.rfc-editor.org/rfc/rfc9110#name-504-gateway-timeout) |
| `505` | HTTP Version Not Supported | The major HTTP version is not supported | Very old or very unusual clients | [§15.6.6](https://www.rfc-editor.org/rfc/rfc9110#name-505-http-version-not-suppor) |
| `506` | Variant Also Negotiates | Content negotiation configuration error | Rare | [RFC 2295 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) |
| `507` | Insufficient Storage | The server cannot store what is needed to complete the request | WebDAV, full disks | [RFC 4918](https://www.rfc-editor.org/rfc/rfc4918) |
| `508` | Loop Detected | An infinite loop was found while processing | WebDAV bindings | [RFC 5842 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) |
| `510` | Not Extended | Marked obsoleted in the registry | Do not use | [RFC 2774 (IANA)](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml) |
| `511` | Network Authentication Required | The client must authenticate to gain network access | Captive portals on hotel and airport Wi-Fi | [RFC 6585 §6](https://www.rfc-editor.org/rfc/rfc6585#section-6) |
### Codes you will see that are not in the registry
Cloudflare returns its own [520 to 526 and 530](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/) to describe problems between its edge and your origin, such as 521 (web server is down), 522 (connection timed out) and 524 (a timeout occurred). nginx logs a non-standard 499 when, as [its source code](https://github.com/nginx/nginx/blob/master/src/http/ngx_http_request.h) puts it, "a client has closed the connection before we even try to send the HTTP header to it." These are useful diagnostics, but generic clients only know they are 5xx or 4xx.
## The mistakes that matter most
Wrong: ~~403 Forbidden for a request with no token at all~~
Right: 401 Unauthorized with a `WWW-Authenticate` challenge
Why: 401 means "authenticate and try again"; 403 means "authenticating will not help." Details on the [401 vs 403 page](https://erroneo.us/developers/http-401-vs-403/).
Wrong: ~~A friendly "Page not found" page served with status 200~~
Right: The same friendly page served with status 404
Why: Google calls this a soft 404 and flags it in Search Console. See [404 Not Found](https://erroneo.us/developers/http-404-not-found/).
Wrong: ~~Rate-limited requests rejected with 503 (nginx `limit_req`'s default)~~
Right: `limit_req_status 429;` plus a `Retry-After` header
Why: A 503 tells clients and monitors that your server is unhealthy. A 429 tells the caller that *they* should slow down. See [429 Too Many Requests](https://erroneo.us/developers/http-429-too-many-requests/).
## Checking a status code yourself
The fastest way to see the real status line, without a browser's friendly error page in the way, is curl:
```
# Status line and headers only (HEAD request)
curl -I https://example.com/some/page
# A real GET, but print only the status code
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/some/page
# Follow redirects and show every hop
curl -sIL https://example.com/old-url | grep -iE "^(HTTP|location)"
```
>
Some servers answer `HEAD` differently from `GET`. If `curl -I` and your browser disagree, repeat the check with `curl -i` (a GET that prints headers) before you trust it.
## From the Error of the Day
1. Oct 22 Developers[CORS errors: the server answered, the browser said no](https://erroneo.us/daily/cors-error/) A CORS error means the browser refused to hand your script the response. The server often answered fine. Fix it with server headers, not frontend hacks.
## Frequently asked questions
**How many HTTP status codes are there?**
The IANA HTTP Status Code Registry is the authoritative list. RFC 9110 defines the core set (100 through 505), and other RFCs add codes such as 429 and 511 (RFC 6585), 451 (RFC 7725), 103 (RFC 8297) and the WebDAV codes from RFC 4918. Codes outside that registry, such as Cloudflare's 52x family, are vendor-specific.
**Is 418 I'm a teapot a real status code?**
It began as an April Fools' joke in RFC 2324. RFC 9110 now lists 418 as (Unused) and keeps it reserved in the registry because it was deployed as a joke so often that it cannot safely be reassigned. Do not use it to mean anything in a real API.
**What is the difference between 301 and 308?**
Both mean the resource has moved permanently. RFC 9110 notes that, for historical reasons, clients may change a POST into a GET when following a 301. A 308 forbids that method change, so use 308 when the method and body must be preserved.
**Should an API return 200 with an error message in the body?**
No. The status code is how clients, caches, monitoring and crawlers learn that something failed. Return the matching 4xx or 5xx code and put the details in the body, ideally in the RFC 9457 problem details format (application/problem+json).
**Which status code should I use for validation errors?**
Use 400 Bad Request when the request is malformed, and 422 Unprocessable Content when it is well-formed but semantically invalid (for example, a well-formed JSON body whose values fail business rules). 422 was originally a WebDAV code and is now defined in RFC 9110.
## Sources
1. [RFC 9110: HTTP Semantics, Section 15 (Status Codes)](https://www.rfc-editor.org/rfc/rfc9110#name-status-codes)
2. [IANA HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
3. [RFC 6585: Additional HTTP Status Codes (428, 429, 431, 511)](https://www.rfc-editor.org/rfc/rfc6585)
4. [RFC 7725: An HTTP Status Code to Report Legal Obstacles (451)](https://www.rfc-editor.org/rfc/rfc7725)
5. [RFC 8297: An HTTP Status Code for Indicating Hints (103)](https://www.rfc-editor.org/rfc/rfc8297)
6. [RFC 8470: Using Early Data in HTTP (425)](https://www.rfc-editor.org/rfc/rfc8470)
7. [RFC 4918: HTTP Extensions for WebDAV (207, 423, 424, 507)](https://www.rfc-editor.org/rfc/rfc4918)
8. [RFC 2324: Hyper Text Coffee Pot Control Protocol (418)](https://www.rfc-editor.org/rfc/rfc2324)
9. [RFC 9457: Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457)
10. [MDN: HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status)
11. [Google Search Central: How HTTP status codes affect Google Search](https://developers.google.com/search/docs/crawling-indexing/http-network-errors)
12. [Cloudflare: Cloudflare 5xx errors](https://developers.cloudflare.com/support/troubleshooting/http-status-codes/cloudflare-5xx-errors/)
13. [nginx source: ngx_http_request.h (499 definition)](https://github.com/nginx/nginx/blob/master/src/http/ngx_http_request.h)
---
Source page: https://erroneo.us/developers/http-status-codes/ · More: https://erroneo.us/llms.txt
==========
---
title: "Common JavaScript errors, explained"
url: https://erroneo.us/developers/javascript-errors/
description: "What \"Cannot read properties of undefined\", \"x is not a function\", CORS and JSON.parse errors mean, with exact browser messages and fixes."
type: guide
section: "Developers"
date_modified: 2026-10-22
publisher: erroneo.us
license: All rights reserved. Quote with attribution and a link.
---
# Common JavaScript errors, explained
> The ten error messages developers paste into search bars most often: what each one means, how Chrome, Firefox and Safari word it differently, a minimal reproduction, and the fix.
JavaScript error messages are short, and they don't always point at the line that caused the problem. They also differ between engines: Chrome, Edge and Node.js run V8, Firefox runs SpiderMonkey, and Safari runs JavaScriptCore, and each words the same failure its own way. The [MDN JavaScript error reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors) lists the variants side by side, and we use it as the main source below. The V8 messages on this page were also checked by running the snippets in Node.js 24.
Every message has three parts: the **error type** (`TypeError`, `ReferenceError`, `SyntaxError`, `RangeError`), the **message**, and a **stack trace**. Read the type first, because it narrows the cause before you read anything else.
| Error type | What it means | Typical cause |
|---|---|---|
| `TypeError` | The value exists but is the wrong kind for the operation | Reading a property of `undefined`, calling a non-function, reassigning a `const` |
| `ReferenceError` | The name can't be resolved, or isn't usable yet | Typos, wrong scope, the temporal dead zone |
| `SyntaxError` | The code (or JSON) can't be parsed | Missing brackets, stray commas, HTML parsed as JSON |
| `RangeError` | A value is outside the allowed range | Runaway recursion, invalid array length |
## TypeError: Cannot read properties of undefined (reading 'x')
This is the most common JavaScript error by a wide margin. You read a property, or called a method, on something that turned out to be `undefined` or `null`. [MDN lists the engine variants](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property):
```
V8 (Chrome/Edge/Node): TypeError: Cannot read properties of undefined (reading 'x')
Firefox: TypeError: "x" is undefined
Safari: TypeError: undefined is not an object (evaluating 'obj.x')
```
The property name in the message is the one you were trying to read. The thing that was `undefined` is whatever sits to its left. In `user.profile.name` failing with `(reading 'name')`, the culprit is `user.profile`.
```
const res = await fetch("/api/user");
const user = await res.json();
console.log(user.profile.name); // profile missing for some users
```
```
const name = user?.profile?.name ?? "Anonymous";
// or check explicitly before you use it
if (user && user.profile) { render(user.profile.name); }
```
Why: [Optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) returns `undefined` instead of throwing. Use it when the data really can be missing. If it should never be missing, find out why it is.
Common sources: an API response shaped differently than you assumed, array access past the end (`items[items.length]`), DOM queries that matched nothing (`document.querySelector` returns `null`), and reading state before an asynchronous load finishes.
## TypeError: x is not a function
All three engines use essentially the same wording here, according to [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_a_function). You put `()` after something that isn't callable.
```
TypeError: o.foo is not a function
```
- **Typos in method names.** MDN's own example is `document.getElementByID`. The method is `getElementById`.
- **The method exists on a different type.** `obj.map(...)` on a plain object fails because `map` lives on arrays. Use `Object.entries(obj).map(...)`.
- **A property shadows the method.** Assigning `this.name = "Ralph"` replaces a prototype method also called `name`.
- **Wrong import style.** Importing a default export with named-import braces, or the reverse, gives you `undefined`.
- **Implicit multiplication.** `2(3 + 5)` is parsed as calling the number `2`.
## ReferenceError: x is not defined
```
V8 / Firefox: ReferenceError: x is not defined
Safari: ReferenceError: Can't find variable: x
```
The name was never declared anywhere the current code can see. [MDN gives three usual causes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined): a typo or missing declaration, a variable declared inside a function and used outside it, or a library (such as jQuery's `$`) used before its `