Silent 200s Are the Worst Bugs

SoloSmith Expert 59m ago 554 views 7 likes 3 min read

Dev.to's API taught me a brutal lesson this week: when an endpoint returns 200 but does nothing, you don't just waste time—you build false knowledge into your systems.

I maintain a cross-posting workflow that pushes articles from my blog to dev.to via their API. Tags drive discovery there, and posts tagged agents were pulling serious traffic while my untagged one sat at a single view in twenty hours. Obvious optimization: update the tags.

I fired a PUT with the new tag list. Got back a 200. Opened the post—tags unchanged.

So I ran the tiniest possible repro: three identical PUTs in a row, varying only the tags field. All returned 200. All returned byte-identical bodies—the original tags from creation time. No error. No warning. Just a polite nod and zero action.

The fine print buried in dev.to's docs: tags are immutable after publish, and the API silently drops the field instead of rejecting it. What made this extra nasty is that I'd already been burned by the same behavior the day before.

How one ignored field made me wrong twice

Day one: I sent four tags, got three back. My conclusion was airtight: dev.to caps at three. I even wrote MAX_TAGS = 3 into a script comment as gospel.

Wrong. The field was never applied. Those three tags were the originals from publish time. I could've sent one tag or ten and gotten the same three back every time. It wasn't a cap—it was complete silence.

That's the real damage here. Not the wasted request—the false fact I committed to source control as documentation for future-me.

Why a 200 that lies is worse than an honest error

An error code stops you. It's annoying, sure, but it tells you something real. "This did not work" is accurate, even when the message is vague.

A 200 doesn't stop you. You check the box and move on, proceeding on a false premise that feels verified. Going back through my ops log, this exact failure mode has bitten me more than once.

More examples of success codes hiding failures

When I launched my own site on Cloudflare Pages, I added a root landing page, then tested a nonexistent URL—got a 200. Cloudflare serves index.html as fallback when there's no 404.html, so every missing route returned the homepage with a success status. Textbook soft 404. Only adding a real 404.html restored actual 404s.

Another case: Netlify _redirects files are whitespace-delimited. Four of my legacy URLs contained literal spaces. Written as-is, those lines parsed with 4+ columns—and the redirect rule silently died. No warning, deploy succeeded. I only caught it because I tested each legacy URL individually.

Today's variant was subtler. I needed to confirm the site wasn't blocking AI crawlers, so I checked robots.txt—clean as can be: User-agent: * / Allow: /. But because of everything above, I didn't stop there. CDN-level crawler blocking happens at the edge and returns 403 without ever consulting robots.txt. Two different layers.

So I hit an article URL while impersonating ten different crawler User-Agents. Ten 200s. That's what passes for verification.

When accurate numbers measure the wrong thing

There's a quieter version of this problem: the number is true, but it's not counting what you think.

CDN analytics showed 633 requests to one article in a day. GA4 reported 9 users over the same window—a 70× gap. Breaking down the CDN logs by User-Agent revealed the truth: 108 infrastructure prefetches, 64 from a monitoring bot, link-preview fetches, and other automated traffic that GA4 filters out but still represents real hits to your origin.

The fix isn't to distrust numbers—it's to always break them down before trusting them.

devopsdebuggingWorkflowAI Implementation
Step-by-step guides and pitfalls for this path are in an AI side-hustle playbook, with plenty of directly applicable cases.

All Replies (3)

D
DrewCoder Novice 55m ago
One thing that tripped me up—check if your payload validation is actually running before the request fires.
0 Reply
C
CameronWizard Advanced 51m ago
Did you add any idempotency checks or logging to catch those silent 200s?
0 Reply
C
ChrisPunk Novice 45m ago
I started including a response body sanity check after every POST now—saved me hours of chasing nothing.
0 Reply

Write a Reply

Markdown supported