AiBook · Jeremy Schoemaker · 2026 · ch-33.html

It Said Success and Did the Wrong Thing

(Spine Ch. 33.)

“After all, you only find out who is swimming naked when the tide goes out.” Warren Buffett, Berkshire Hathaway 2001 Chairman’s Letter (2001)

The log line said No phrases matched. That is a boring sentence. I read it, believed it, and went to look at something else. It was 8 August 2026, the tables in airank were empty, and the sentence was completely accurate: zero phrases were in the table, so zero phrases matched. Three separate database dumps were reporting success at the same time. One of them was 4 KB. Another said six binlog files shipped, and it was right about the number six. The documentation, which I wrote, said the backups were broken. The only backup in the building that actually worked was the one my own docs had written off.

Bottom line: A failure that announces itself is a Tuesday. You read the stack trace, fix it, go to lunch. The expensive failure returns exit code 0, prints a green checkmark, and hands you a 4 KB database dump you won’t open for six weeks. Every layer you trust reports on its own behavior, not the outcome you wanted. My incident log for 8 August 2026 counts nine systems in airank announcing success while delivering nothing; I can name five of them in this chapter. The tooling wasn’t broken. It was working exactly as written, reporting on the wrong thing.


When it bites


The pattern

Every piece of software in your stack answers a question, and it is almost never the one you’re asking.

mysqldump answers “did I exit without an unhandled error,” not “does this file contain your data.” AWS Lambda’s runtime answers “did the invocation complete.” An error inside your function code comes back as HTTP 200 with the failure buried in the response body. Docker’s health check answers “did the container’s declared probe return zero,” not “is this process holding the config you edited eleven minutes ago.”

None of these are lies. The gap has a shape:

Wrong table. The write succeeded, but it went somewhere else. The row count went up, so the metric looks healthy.

Wrong environment. The migration ran against staging. Staging is now beautifully migrated.

Wrong record. The update matched zero rows and UPDATE doesn’t care.

Correct no-op. The guard clause fired, the function returned, nothing happened, and the log line is often literally true. On 8 August airank logged No phrases matched. Also the sound a database makes when its tables have been emptied.

Backup vendors love to quote a scary share of restores that fail even though the backup reported success. Every version of that number I chased pointed at other vendors quoting each other, never at a study. So I am not going to hand you one. The mechanism is the claim: a backup that has never been restored has a status, not a proven outcome.

I went looking for somebody else’s receipt and came back empty. A name-brand post-mortem putting a dollar figure or a customer count on a 200 OK that lied: vendor pages define the pattern, and I found zero incidents with a bill attached. So the worked example below is my own company, which is the weakest thing about this chapter and also most of the evidence for it. Nobody files an incident report for the outage that never paged anybody.

Agents make this worse. A human who breaks a deploy usually watched it happen. An agent reads the same green output and writes “deploy successful” into a handoff.

The defense isn’t more logging (that’s the thing that lied to you). It’s one move: re-run the smallest thing that would fail if the claim were a lie. docker service ls, not the deploy output. ls -la on the dump, not the backup’s status email. Byte counts, row counts, commit counts: cheap and immune to the thing you’re checking.


One worked example

airank, 8 August 2026. The database connection dropped and the tables came back empty. What made the next several hours expensive wasn’t the data loss, it was that every instrument I reached for to understand it also reported success.

The log said No phrases matched. Correct output, wrong conclusion, reads like a quiet afternoon.

Three artifacts told me the backup situation, and all three were wrong:

  1. mysqldump ran with a wrong flag. The error was suppressed. The dump was 4 KB and contained nothing useful.
  2. The binlog shipper reported six files shipped over rsync, and it was honest about the six. File 4 arrived truncated. It was counting file names, not file contents.
  3. The documentation, written by me, said the backups were broken. A fourth artifact nobody was measuring, a 15-hour-old snapshot, was intact the whole time. It was the one my own docs had written off.

Read that third one again. Jeremy Schoemaker wrote a document that talked him out of the only asset that could save him. I got pwned by a paragraph I typed myself and then obeyed for months. Somewhere in there was a green checkmark repeating on a loop like Badger Badger Badger (2003): same cheerful thing, no information in it, and I hummed along for six weeks.

Outcome: I recovered 577 observations out of object storage the ugly way, pulling question text off stored artifacts and matching it back to phrases, then restored the database from that 15-hour-old backup the docs had declared dead. Having stopped believing green checkmarks that day, I found more of the same class already in the codebase: a webhook verifier rejecting 100% of valid signatures while returning a normal response, and environment variables never read after a container restart that proudly reported Up 6 seconds (healthy).

Same class, different night. On 7 August the committed stack.yml said replicas: 0 and SHARD_TOTAL: 1 while production ran 20 replicas with AIR_SHARD_TOTAL=20, so any docker stack deploy from the repo would have taken production to zero and reported success on the way down; I caught it before anybody ran it, because the running image didn’t match the committed image, and the same handoff claiming seventeen branches needed merging turned out to need zero. On 13 August the lies ran the other direction: eight test failures on clean main were eleven agents sharing fixtures, and three logged merge failures were the shell’s noclobber blocking a redirect so the merge commands never ran at all, which a solo 17 of 17 run and a merge-commit count of zero settled in under a minute. On 11 August the AI Readiness Report passed 611 tests while comparing a visitor’s page against Google search results, when the product’s whole premise is that assistants don’t rank pages that way.


The quiet failure

The loud failure is the deploy that errors out: red text, bad afternoon, obvious fix.

Your monitoring watches the reporter, not the outcome.

Uptime dashboards go green when a service responds. A webhook endpoint rejecting 100% of valid signatures responds beautifully and fast. Your p99 improves while the integration is dead.

The green result becomes the memory. An agent reads “deploy successful,” writes it into a handoff, and eight hours later another agent builds on a production state that never existed.

You build the retry on top of the lie. If the operation reports success, nothing retries it. Silent failure is the one mode your resilience layer can’t see.


Do / don’t

Do

Don’t


Where this sits in the book

Ch. 17 is the agent that reports done and did nothing: this chapter with a model in the loop instead of a shell command. Ch. 36 is verification, proving an outcome with a second instrument. Ch. 38 is the blast radius, what a confidently wrong success costs once other systems build on it. Ch. 15 is where this starts: a plan full of green checkmarks is a plan nobody re-measured.


Sources and receipts

Thesis is Jeremy’s (success is a claim about the operation, never about the outcome): argument, not citation.

Verified:

Hedged, not verified: