Dev.to · 5 min read

A 200 From the Wrong System: How Two Pages Stayed Invisible for 17 Days

A 200 From the Wrong System: How Two Pages Stayed Invisible for 17 Days

Two pages on my site went live on July 22. On August 8 they had zero impressions in Google. Not low. Zero, across three weekly exports. URL Inspection didn't say "crawled, not indexed." It said Google could not recognise the URL. Referring sitemap: none detected. Referring pages: none detected. Last crawl: not applicable. Never discovered. Seventeen days. The pipeline was green the entire time My deploy is a small chain: rsync the file, import it into MySQL, restart the service, ping IndexNow. Every step returned success. The last step returned 200 on every URL, every deploy, for three weeks. Here's what I'd never examined: IndexNow doesn't feed Google. It's Bing, Yandex, Seznam, Naver. My green light was real — it was just about a different search engine than the one whose console I was reading. That's the whole bug, and it isn't an SEO bug. It's the generic one: system A returns 200 → I conclude something about system B → nothing in the response object ever objected If you've ever read a webhook 202 as "the downstream processed it," or a CDN purge 200 as "the edge is cold," it's the same shape. What actually broke Search Console's Sitemaps report: Submitted: 2026-07-22 Last read: 2026-07-22 ← seventeen days ago Discovered: 101 URLs ← the file has had 117 for weeks The two pages went live on July 22 — the same day as the only read. Google fetched the sitemap and moved on, within hours of the file changing. Then nothing brought it back, because a sitemap changing on your server notifies nobody. There is no push. It's a pull-only resource with no cache invalidation, and if the consumer doesn't happen to return, your new URLs live in a document no one is reading. Resubmitting took two minutes. Read immediately, 117 URLs. So I wrote the check. It doesn't catch the bug. This is the part worth more than the fix. I wrote a post-deploy verifier. It does two things: // 1. every published, non-redirected page appears in the live sitemap const missing = published.filter((p) => !inSitemap.has(p.url)); // 2. every sitemap URL is fetchable and indexable if (!r.ok) bad.push({ u, why: HTTP ${r.status} }); else if (/noindex/i.test(robots)) bad.push({ u, why: "noindex" }); else if (finalUrl !== u) bad.push({ u, why: redirects to ${finalUrl} }); Current output: Check 1 — published content present in sitemap: 35/35 Check 2 — sitemap URLs fetchable and indexable: 117/117 Both of those would have passed on July 23, and every day after. The sitemap was correct. The pages were correct. Everything on my side of the network boundary was fine. What failed was the consumer's decision to come back, and there is no assertion I can write locally that observes it. So the script prints its own limit rather than implying coverage it lacks: Check 3 — was the sitemap actually READ by the search engine? NOT CHECKABLE FROM HERE. Both checks above passed on the day two published pages had never been discovered, because the file was correct and the consumer simply never came back for it. Verify in Search Console > Sitemaps that "Last read" is more recent than your latest publish date. IndexNow returning 200 does not cover this: it does not feed Google. The assertion you need is on the other side of the boundary. Local checks verify your artifact. Only the consumer can tell you it consumed it. That generalises past sitemaps: you can validate the message you published, but "was it delivered, and did anyone read it" lives in the broker's API, not yours. The checker's first run was wrong One more, because it's the third time this week I've shipped a verifier that lied on its first run. Check 1 initially reported 11 missing URLs. All 11 were pages I had deliberately consolidated — their markdown files still exist locally, but the URLs 301 elsewhere. Absent from the sitemap is exactly correct for them. My check was flagging correct behaviour as failure. // A checker that cries wolf on correct behaviour gets muted, // and a muted checker is worse than none. if (redirected.has(pathOnly)) continue; This week I also had a data audit report "three datasets don't store raw responses" — they had one API timeout each, which correctly stores an error and no response. And a citation parser that counted a brand's name as a source, because the brand is literally called Monday.com. Every one of those was a first run. Every one produced a plausible, alarming, false number. So the habit I'd recommend over any specific check: before you believe your new verifier, make it fail on purpose, and read every row it flags. If you can't explain each flag, the tool is measuring something other than what you named it. Three things to check today In Search Console → Sitemaps, is Last read more recent than your most recent publish? One click. In three months of running this site I had never once looked. Does your deploy pipeline's success signal come from the system you're actually measuring? Mine didn't. When your verifier passes, do you know which failures it's structurally incapable of seeing? Write that in the output, not the README. Mine now prints it every run.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

Related stories