6 Claude Code failures that all reported success

Svelte code displayed on a dark computer screen in a code editor

Green pipeline. Closed issue. Successful deploy. All of those fired while the thing was broken.

Andrew Connell spent April through October 2026 migrating his entire content library to andrewconnell.com using Claude Code, Anthropic’s agentic coding tool. He logged every failure. The pattern that runs through almost all of them: the failure reported success. No red builds, no alerts, no obvious signal. Just broken behavior hiding behind green checkmarks.

The second pattern is just as important. Most failures traced back to context the agent never had, because it lived in his head instead of the repo. Claude can’t read minds. If the goal, the constraint, or the convention isn’t written down somewhere the agent can read it, the agent will make a reasonable decision with incomplete information.

️ The Six Failures at a Glance

FailureWhy it looked fineHow it was caught
release-please double-bracket bugEvery run reported successClaude, six days later, reviewing an unrelated PR
8,502 timecode links to the homepageThe build passedManual click test on a preview lesson
PostCSS config missing from gitLive site kept serving last good CSSCI clean-clone build failed
CSP issue closed three timesRelease PRs said “closes”Manual reopen each time
CI cache that saved nothingactions/cache step always greengh cache list showed one entry, never two
robots.txt with no rulesCarried an AI policy lineA paid scanner

The Double-Bracket Bug That Stalled Releases for Six Days

This one is almost poetic in how it broke. The site’s release PR title carried two skip markers: [skip unit] and [skip e2e]. When release-please merges a release PR, it re-parses the title to recover the version it should tag. The parser in every published release-please action escapes only the first [ and the first ]. The second group compiled as a regex character class. The anchored pattern could never match. No tag, no GitHub release, no new release PR proposed.

Every run logged ✖ Bad pull request title, buried in line 38 of a job log whose overall status said success. Two feature commits piled up on main with nowhere to go. The stall lasted six days, surfacing only when Claude reviewed version-advisor output on an unrelated PR and the numbers didn’t add up.

The part that stings: the double-bracket pattern came from Connell’s own CLAUDE.md, which recommended it to the agent. The docs produced the bug. Upstream fixed the escaping in June 2026, but as of October 2026 no release of the GitHub Action bundles the fix.

Guardrail added: A single umbrella marker [skip tests] replaces both, and scripts/release-title-pattern.test.mts round-trips every configured title pattern through the parser release-please actually ships. Add a second bracket group and the build fails before it can reach a release PR.

3D rendered ai text on dark digital background

8,502 Lesson Links That Went Nowhere

Course lessons are packed with timecode links. A link like [the licensing answer](?t=94) should jump a video to 94 seconds. Hugo’s link render hook treats a destination that isn’t absolute as an internal link, looks it up with GetPage, and fails the build on any internal link it can’t resolve. Except when the path is empty. GetPage "" returns the home page. All 8,502 timecode links silently rendered as href="/?t=94" and the build reported success.

He caught it by clicking one of those links during a manual preview check in September 2026. None of it reached readers because every lesson was still a draft, and production doesn’t build drafts. The Playwright test suite didn’t catch it either. Almost all tests were screenshot baselines comparing how a page looks, not what happens when a reader clicks something.

Guardrail added: The render hook now fails the build on an empty link path. It failed the first build of the article being referenced here, because Claude had written the example as a real Markdown link. End-to-end behavioral tests are still on the backlog.

The Launch-Day Config That git Never Tracked

On April 2, postcss.config.js was committed inside the theme. On April 3, a Claude co-authored commit added themes/**/*.js to .gitignore to keep compiled JavaScript bundles out of the repo. On July 7, a launch-morning commit renamed the theme folder from v6 to v7. Git committed the delete of the old config path and silently ignored the new one.

Every local build worked because the file still existed on the machine. Every clean build panicked: postcss config "assets/css/postcss.config.js" not found. Production deploys failed, but a failed deploy never publishes, so the live site kept serving CSS from the last good build. It looked fine. CI caught it because CI is a clean clone. The issue opened and closed within ten minutes on launch day. The fix was one committed file.

Guardrail added: The config is now TypeScript (postcss.config.mts), so the *.js glob can’t touch it. No automated check yet that every file a template references is tracked in git. Connell calls that an honest gap.

The CSP Issue That Got Closed Three Times

The Content Security Policy shipped in report-only mode, where browsers report violations instead of blocking them. Flipping it to enforce was tracked in its own issue. The commit convention uses related #NNN to mean “this contributes but doesn’t finish.” GitHub doesn’t treat related as a closing keyword. release-please’s changelog generator does something different: it rewrote related #352 into closes #352 in the release PR body, and GitHub acts on the text in the PR body.

The issue closed three times from release PRs while CSP was still in report-only mode:

  • August 15: release PR #415
  • August 21: release PR #458
  • August 30: release PR #503
  • September 2: manual deploy, CSP actually enforcing

The third close hit a replacement issue titled “Flip CSP… (for real this time).” The same mechanism later closed a provider sign-in issue before the new sign-in service existed.

Guardrail added: Every PR that changes deployed behavior now carries a post-deploy verification step. Before the merge, Claude runs a set of checks (usually curl commands) against the live site and records responses. After the deploy, it runs the same checks. For the CSP flip, the check looks for content-security-policy-report-only before and content-security-policy after. If the second run still says report-only, the issue stays open regardless of what the release PR said.

brown grasshopper on green leaf in close up photography

⚙️ Three More Failures That Fit the Same Pattern

A CI cache that saved nothing for months

Hugo builds cached two things in GitHub Actions: generated images and remote resources like YouTube thumbnail metadata. The second cache pointed at resources/_gen/getresource, a folder Hugo never writes to. Hugo keeps remote fetches in its own cache directory. actions/cache quietly saves nothing when the path doesn’t exist, but the step stays green. gh cache list showed one Hugo cache entry, never two. The fix pins the correct path in hugo.yaml.

A robots.txt with no rules

The file carried a Content-Signal: ai-train=no line, which is an IETF draft that almost no crawler reads. The per-bot Disallow groups that GPTBot, ClaudeBot, and others actually honor were missing entirely. A paid scanner caught it. Connell notes he’d been asked whether he wanted a gate for this and said no, because the scanner would catch it. The scanner did, but he never validated it with his own tools.

Agent-readiness features failing agents

In September 2026, a scanner called afdocs found that Markdown output for agents was emitting raw HTML, and that the directive telling agents where to find it was an HTML comment, which is invisible to the agents it was meant for.

The Rule That Would Have Prevented Most of This

Verify after the deploy, not just before the merge. Unit tests and green CI prove the code does what the tests say. They don’t prove the deployed thing works. A single merge on this project can release the site, several Cloudflare Workers, and apps on Azure Container Apps. Each pull request now carries a throwaway verification script, and an issue doesn’t close until that script passes after the deploy.

The second rule is about context. The more of the project Claude can read in the repo, the better its decisions. Not a history, not a story. Just what’s true now, so the agent doesn’t have to guess. That discipline matters even more given that Connell was running up to five Claude Code sessions in five git worktrees simultaneously, and sometimes they collided.

One reversal worth noting: he built sign-in on Microsoft Entra External ID, hit the point where he no longer understood what the system was doing, asked Claude in a separate chat whether he was over-engineering it, and scrapped the whole thing for two plain database tables. He doesn’t count that as a failure. Learning something and simplifying is the process working.

The Replication Checklist

  • Write the context down. Repo docs that state current state, not history. The agent reads the repo, not your mind.
  • Verify after every deploy. Record expected behavior before merge, check it after deploy, close the issue only then.
  • Give each incident a test. Make the next silent failure loud with a targeted build check.
  • Don’t rely on scanners alone. They catch things after the fact. You need checks that run on every deploy.
  • Plan around limits the agent can’t move. YouTube’s API quota is counted in cost units per call. The documented 100 uploads per day ran out at 89, then 81, then 47. Claude didn’t set that pace. Google did.
  • Separate errors from warnings. Fail the build on real errors. Log warnings without blocking. The distinction matters at scale.
Stay on top of AI & Automation with BizStack Newsletter
BizStack  —  Entrepreneur’s Business Stack
Logo