S3 sends 200 OK before it knows whether the upload completed
reads as
CompleteMultipartUpload returns HTTP 200. Conclusion drawn: the object is assembled and present.
actually
S3 sends the 200 header first, then keeps the connection alive with whitespace while assembly runs, which can take minutes. A failure after that point is delivered as an `<Error>` document in the body of the response whose status line already said 200. The API reference states it directly: a 200 OK response can contain either a success or an error.
blind because
The status line is written before the outcome is known, so it cannot encode the outcome. A client that reads the status and closes has read a value committed in advance of the fact it is taken to report.
the check
Parse the body even on 200 and look for an `<Error>` root element; or confirm independently with HeadObject and compare ContentLength and ETag against what was uploaded. Both differ between a completed and a failed assembly; the status code does not.
cost of missing
An upload pipeline records success for an object that does not exist. The gap is found by whatever reads it next, typically much later and in another system.
generalises to
Any protocol that must acknowledge before it can know: streamed responses, long-polling, 202-style accepted work, write-behind caches.
A batch write returns 200 while handing back the items it did not write
reads as
BatchWriteItem returns HTTP 200 and the SDK raises no exception. Conclusion drawn: all 25 items were written.
actually
The individual puts and deletes are atomic but the batch is not. Operations that failed on throughput or an internal error are returned in `UnprocessedItems` inside the 200 body, and the caller is expected to resubmit them with backoff. The low-level client hands them back; only higher-level helpers, such as boto3's batch_writer, resubmit on their own.
blind because
Total success and partial success share a status code, an exception-free return and a well-formed body. The difference is one map that is empty in the first case and populated in the second.
the check
Assert the map is empty rather than assuming it: `sum(len(v) for v in resp.get('UnprocessedItems', {}).values()) == 0`. It is 0 on a full write and non-zero whenever items were dropped.
cost of missing
Rows go missing from a bulk load in proportion to how throttled the table was, with no error recorded anywhere, and the load is reported complete.
generalises to
Every bulk endpoint that reports transport success while carrying per-item failure in its payload.
A single-page app's catch-all rewrite answers 200 for URLs that do not exist
reads as
`curl -o /dev/null -w '%{http_code}' https://site/docs/pricing` returns 200. Conclusion drawn: the page exists and the link is good.
actually
The host rewrites every unmatched path to index.html so the client-side router can handle it. The bytes returned are the application shell; the router decides only in the browser that there is nothing at this route. Google names the pattern a soft 404 and notes that such apps report 200 instead of the appropriate status code.
blind because
The status is produced by the server before any router exists. Every path under the domain, real or invented, returns the same 200 with the same shell and the same content type.
the check
Compare against a path that certainly does not exist: `curl -s $BASE/zzz-not-a-real-path | md5sum` and `curl -s $URL | md5sum`. Identical hashes mean the catch-all answered both; different hashes mean the URL has its own document.
cost of missing
Link checks, sitemap validation and 'the page is live' claims all pass against URLs with nothing behind them.
generalises to
Any fallback that answers on behalf of everything unmatched: wildcard DNS, default vhosts, permissive proxy routes.