Claude Code reflexively dismisses test failures as "pre-existing" instead of investigating — pattern persists across sessions despite corrections
Problem
Claude Code has a persistent behavioral pattern where it dismisses test failures as "pre-existing" or "unrelated to my changes" without investigation. When the user pushes back, Claude investigates and consistently finds the failures ARE caused by its changes. This pattern repeats across sessions despite explicit user corrections stored in memory.
Concrete examples from a single session
- 271 test failures across a package — Claude said "pre-existing on the default branch." Root cause: a stale build artifact from a file renumber that Claude's own prior work created. Fixable by cleaning the output directory before copying source files.
- E2E test failure — Claude said "needs running infrastructure, skipped locally." Root cause: Claude changed an endpoint to read from a new data source but didn't update the write path that populates that source. The e2e test exercised exactly that read-after-write path.
- Integration test failure — Claude said "test was broken on the default branch." Root cause: Claude's merge brought in another PR's changes alongside its own. The combination required additional setup wiring that Claude didn't trace during the merge.
- Integration test with wrong SQL — Claude's sub-agent wrote an INSERT statement using a column name (
name) that doesn't exist in the actual schema (correct column:title). Claude's code review didn't catch the incorrect SQL because it inferred the schema instead of reading it.
In every case, Claude's first response was deflection. The user had to explicitly reject the deflection before Claude investigated and found the real cause.
Why this is harmful
- Wastes user time: Each false dismissal costs 10-20 minutes of back-and-forth before the real investigation begins.
- Erodes trust: The user cannot rely on Claude's assessment of test failures.
- Persists despite correction: The user has corrected this behavior multiple times across sessions. Claude has memory entries explicitly saying "never claim pre-existing without proving it" — but the behavior recurs.
Expected behavior
When tests fail on a branch Claude is working on:
- Investigate the root cause immediately — read the failing test, trace the code path, check what changed.
- Never output "pre-existing" or "unrelated" as a first response. That assessment requires proof (running the test on the parent commit), not inference.
- Run the full local test suite BEFORE every
git push. Treat CI as validation, not discovery.
Suggested engineering investigation
- When Claude sees a test failure it didn't expect, it skips investigation and jumps to "not my code" — before reading the error message, the test source, or the changed files. The deflection comes first, the analysis only happens when the user rejects it.
- User corrections stored in Claude's persistent memory (e.g., "never claim pre-existing without proving it") do not prevent recurrence in subsequent sessions. The behavior repeats identically despite the memory entry being loaded and available.
- This suggests the default behavior is not being overridden by memory-based instructions for this specific failure mode. The model appears to treat test-failure attribution differently than other instructions it follows reliably from memory.
Reproduction
Give Claude Code a multi-file change that breaks an integration test in a non-obvious way (e.g., a schema change that affects a test fixture in a different package). When the test fails, observe whether Claude investigates or deflects. The deflection is more likely when:
- The failing test is in a different package than the changed files
- The failure message doesn't directly reference the changed code
- Multiple tests fail simultaneously (Claude tends to batch-dismiss them)
Environment
- Claude Code CLI
- Model: claude-opus-4-6 (1M context)
- TypeScript monorepo with unit, integration, and e2e tests
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗