Card 07/ 09

GotchaDifficulty: Intermediate2 min

200 OK With an Error in the Body

A response that says 200 and carries an error is cached, counted as success and retried by nobody.

An API that returns 200 OK with an error message in the body hides the failure from every program that reads only the status code. Caches store it, monitoring counts it as success, and retry logic never runs. The code must match the outcome, because the code is what software acts on.

Picture a dashboard showing 99.9 per cent success during an outage. Customers cannot load their orders, support is flooded, and every graph is green. The order service has been answering every failure with a 200.

The symptom. Users report failures that monitoring does not see, cached error messages served long after the fault is fixed, and clients that crash parsing a body they expected to hold an order.

The same failure sent as a 200 and as a 404

200 OK{"error": "order not found"}

A cache may store it and serve it to the next caller. The dashboard counts a success. The client's error handling is skipped, and its code tries to read an order that is not there.

404 Not Found{"error": "order not found"}

The cache stores it only briefly, by its own rules for errors. The dashboard counts a client error. The client's error branch runs, and its retry logic knows not to resend.

Why it happens. Some frameworks make returning a body easier than setting a code. Some teams reason that the request "worked" because the server answered. And APIs built on older remote-call styles carried every error inside a 200 by design.

What it costs. Outages that monitoring misses, errors cached as if they were content, and every client forced to parse each body to learn whether the call worked.

What to do. Send the code that matches what happened, and put the detail in the body. A failed lookup is a 404, a bad value a 422, a crash a 500. The body then explains; the code decides.