I Shipped [object Object] in My Meta Tags for Five Months: How Claude Code Caught It
- •
- 8 min
Forward Deployed Engineer · Dubai
Every Saturday morning I pull a Google Search Console export and a GA4 export and write myself a short SEO report. It is a habit, not a job — fifteen minutes of looking at what moved, what did not, and what is quietly broken. This is the story of a week where the "quietly broken" part turned out to be five months deep, and where the most useful pair of eyes in the room was not mine.
The fifteen-minute habit that found a five-month bug
The report flagged a Search Console drilldown I do not see often: "Discovered — different canonical" on one of my articles. Google was indexing some other URL as the authoritative version of my page. I opened the article's page component with Claude Code — my daily AI agent, and the thing I reach for before I reach for a terminal — to confirm the canonical tag was set correctly.
It was. While I was in there, I asked it to sanity-check the rest of the rendered metadata, almost as an afterthought. That is when it surfaced something I had never once thought to look at, in twenty years of shipping software:
<meta property="article:published_time" content="[object Object]"/>
<meta property="article:modified_time" content="[object Object]"/>
![View-source of a real article's head: the published-time and modified-time tags both emitting [object Object] instead of a date](/_next/image?url=%2Farticles%2Fthe-meta-tag-bug-i-shipped-for-five-months%2Farticle-object-object-time.png&w=2048&q=75&dpl=v0-96-0)
Every article. On every page. Since the blog launched on 23 January. Nearly five months of shipping [object Object] into the head of every post.
Why it was invisible
Here is the uncomfortable part: the page looked perfect. The publish date rendered correctly on screen — "May 22, 2026" — because the visible <time> element runs the value through a date formatter before display. Nothing threw an error. Nothing looked wrong. Lighthouse was happy. The article read fine.
The bug lived entirely in the <head>, in two tags that no human ever reads. You only catch it in three places: view-source, a social-card debugger, or a tool that systematically inspects the emitted HTML line by line. I had never done the first two for my own date tags, because why would I — the date was obviously working. I could see it on the page.
That is the whole trap. The bug was not in what I looked at. It was in what I had decided I no longer needed to look at.
The type that lied
The root cause is a small, almost funny detail. At the top of every article I write the publish date without quotation marks:
date: 2026-05-22T10:00:00+00:00 # no quotes around it
To a human that is obviously a date. To the software that reads the file, an unquoted timestamp like that is not text — it gets turned into a special internal "date object." Meanwhile, the rest of my code had been promised, in writing, that this field would always be plain text. So one part of the system was handing over an object while another part was certain it would receive a string.
The browser got an object where it expected a string, shrugged, and printed the only thing it could: [object Object]. The page that displays the date on screen never hit this, because it runs the value through a formatter first. The hidden meta tags took it raw — and broke, silently, on every post.
What it actually cost, and what it did not
"My blog was broken for SEO for five months" would get clicks. It would also be wrong. article:published_time is an OpenGraph signal — it feeds social cards, some AI crawlers, and freshness heuristics. It is not a primary Google ranking factor. And the field Google's structured data actually leans on, the JSON-LD datePublished, was correct the whole time, because that one code path coerced the value properly.
So here is the true, smaller version of the damage:
- My social and AI-scraper date signals were garbage on every post.
- My "last updated" signal never moved — even on articles I rewrote — because the modified date was wired to the publish date, not the real update date.
- Every share card described its image as the placeholder "OpenGraph Image" instead of the actual headline.
Not catastrophic. But it is exactly the kind of slow, invisible signal-rot a credibility-driven blog should never ship — and exactly the kind nobody notices, because nothing on the page ever looks wrong.
If I am going to write about engineering rigor, the meta tags on the article had better not say [object Object].
The signal I had misread completely
The second lesson is the more embarrassing one, because it was not a typo. It was a wrong conclusion stated with confidence.
Remember the drilldown that started all this — "Discovered — different canonical." In my own SEO report, I had already explained it to myself: two of my articles were too similar, and Google was folding them together. I had even gone and added cross-links between them to "fix" it.
Wrong. When Claude Code pulled the actual canonical URL Google had selected, it was not a sibling article at all. It was the Medium copy. Google had decided that my Medium repost was the authoritative version of my own writing — because Medium gets indexed within hours while my blog can sit in "Discovered — not indexed" for weeks, and a cross-domain canonical tag is only a hint, one Google overrides when the lower-authority page is not indexed first.
My fix had been aimed at a problem that did not exist. The real fix was a change to my publishing process, not my content. And I would have kept politely fixing the wrong thing for weeks if I had trusted my interpretation of the data instead of looking at the data itself.
The fix that mattered more than the bug
The fast fix was obvious: wrap every date in new Date(...).toISOString(). I did that first, in four places, and the tags went green.
Then I stopped. Patching each consumer is whack-a-mole, and I had proof: the call-site approach had already missed one. My articles index page carried the same raw-date bug, untouched, because it lived in a different file. If I patched four spots today, the fifth would surface in six months, and the next new page would reintroduce it.
The right fix was one level down. Normalize the dates once, at the single point where frontmatter is parsed, so the string type finally becomes true and every consumer — the ones I had found, the ones I had not, and the ones I have not written yet — receives a real string. One change at the boundary instead of N changes at the edges. The index-page bug fixed itself the moment I made it.
A special case bolted onto shared infrastructure is usually a sign the fix is not deep enough.
That is the part I care about most as an engineer, and it is the part where the AI was genuinely sharp: not "here is the bug," but "you are fixing this at the wrong altitude."
Where Claude Code helped, and where it did not
I want to be precise about the division of labor, because "AI found my bug" is the lazy version of this story.
What Claude Code did well: it read every consumer of the date field across the codebase in seconds, noticed the one I would have missed, argued for the root-cause fix over the quick patch, and verified each change by actually curling the running pages and diffing the meta tags before and after. That is not magic. It is tireless, systematic checking — the exact thing humans are worst at, precisely because we trust what we already believe.
What it did not do: decide that the OpenGraph date bug was low-impact and the freshness signal was the thing actually worth caring about. Decide that "broken for five months" was an overstatement I should not publish. Notice, unprompted, that my own report's diagnosis was wrong — I had to point it at the actual canonical; left alone, it would have cheerfully helped me implement my incorrect fix. The judgment stayed mine. The labor, and the catching of my blind spots once I aimed it at the right place, was the multiplier.
(This article was drafted with Claude Code too — including the part where it talked me out of the dramatic headline.)
The uncomfortable lesson
I have been writing software for years. I know what a meta tag is. I know YAML coerces dates. This bug was not beyond me — it was beneath my attention, which is worse, because attention is the one thing that does not scale with skill.
Skilled does not mean immune. It means your bugs relocate to the places you have stopped looking. The ones that survive are never the hard ones. They are the ones invisible in the rendered page, that throw no error, that look perfect until something inspects the source line by line and refuses to assume the date is fine just because it shows up on screen.
That "something" does not get bored. It does not trust the type annotation. And it does not believe, the way I did, that a thing it has seen working a hundred times must be working the hundred-and-first. That is the entire value — not that it is smarter than me, but that it has no investment in my assumptions.
I use AI the way I described here: embedded in the real work, checked against reality, with the judgment kept human — not bolted on as a demo. If you want that built into how your team actually ships, see the AI Solutions service or book a call.