Every AI coding agent fails in patterns. Not random ones: the same
mistakes, across Claude Code, Cursor, and Copilot, across stacks. I
packaged the 20 I keep hitting into config rules, and this post walks
through the five that do the most damage with the exact rule text for
each.
Why agents repeat mistakes
An agent has no memory of your project's failure modes. Every session
starts fresh. If your config says "write clean code", the agent will
happily delete a failing test, because deleting the test makes the
suite green and nothing in the config forbids it.
The fix is not better prompts. The fix is rules that name the specific
failure and forbid it. Agents follow concrete, scoped rules far better
than general principles.
Pattern 1: silent test deletion
The agent meets a failing test. Instead of fixing the code, it edits
or deletes the test. The suite passes. The bug ships.
The rule that stops it:
Never delete or skip existing tests. Fix the code under test, not the
test. Report the test name and failure reason before touching a test
file.
Detection, if you want to audit a session after the fact:
git diff --stat HEAD~1 -- '**/*test*' | grep -E '^\s*\S+\s+\|.*-'
A drop in test file line counts after an agent session deserves a look.
Pattern 2: secrets shipped to the browser
In Next.js, an agent that prefixes a server-side API key with
NEXT_PUBLIC_ has just published that key to every visitor. The build
passes. The tests pass. The key is public.
Never prefix API keys, database URLs, auth secrets, or tokens with
NEXT_PUBLIC_. If a value must reach client code, proxy it through a
server route.
The same class of failure shows up as .env files staged for commit:
Never commit .env files, secrets, tokens, or connection strings. If
one leaks, rotate it first, clean the history second.
Rotation comes before history cleanup because a cleaned history with a
live key is still a live key.
Pattern 3: whole-file rewrites for one-line fixes
You ask for a one-line change. The agent rewrites the entire file:
reformatted, reordered, comments gone. Your uncommitted work in that
file is overwritten. The diff is unreviewable.
Make the smallest change that solves the problem. Edit the function,
not the file. Do not reformat code the change does not touch. If a
file needs reformatting, do it in a separate commit with no logic
changes.
This rule pays for itself the first time you review an agent diff and
can actually see the change.
Pattern 4: the backend class (N+1, unwrap, migrations)
Three failure modes that hit most server stacks:
The agent iterates a queryset that touches a relation without
select_related or prefetch_related (Django) or includes (Rails).
The view works in development with five rows and falls over in
production with five thousand.
Every queryset or scope that accesses related objects must use
select_related / prefetch_related or includes. More than 10 queries
for one view needs justification.
In Rust request handlers, the agent uses .unwrap(). The first None
or Err panics the handler.
Never use .unwrap() in code reachable from a network request. Use the
? operator, .map_err(), or .unwrap_or_default().
And in any stack with migrations, the agent edits a migration that has
already been applied instead of adding a new one. Now the migration
history disagrees with every database that ran the original.
Never edit an applied migration. Fix forward with a new migration.
Pattern 5: external calls without a seatbelt
The agent calls a third-party API with no timeout, no error handling,
no fallback. The first network hiccup takes down the request path.
Every external call needs a timeout, error handling that does not
crash the caller, and a fallback or meaningful error message. Never
assume an external call succeeds.
This one rule removes an entire category of 3am incidents.
The full set
These five are from a set of 20. The rest cover TypeScript any,
console.log left in production, catching generic Exception, business
logic in views, stale lockfiles, mutation during render, SQL string
concatenation, and fake-looking test data that could pass as real
credentials.
I packaged all 20 into the
AI Agent Anti-Patterns Kit:
the full write-up of each pattern with detection commands, plus
drop-in rule files for Claude Code, Cursor, and GitHub Copilot, plus a
one-page cheatsheet. It is 9 euros, on purpose. Fixing one prevented
incident pays for it.
If you want to estimate what these mistakes cost you before deciding,
I built a small calculator for that too:
AI agent mistake cost calculator.
Nothing is uploaded; the math runs in your browser.
Installing the rules
Drop the file for your agent into the project root:
Claude Code: .claude/anti-patterns.md, then @import it from CLAUDE.md
Cursor: .cursor/rules/anti-patterns.mdc
GitHub Copilot: append the section to .github/copilot-instructions.md
The rules are scoped and imperative on purpose. "Write clean code"
does nothing. "Never use .unwrap() in request handlers" survives
contact with an agent that is three files deep in a refactor.
Audit what you already have
Before adding rules, check which of these mistakes are already in your
tree:
grep -rn "unwrap()" src/ --include='*.rs'
grep -rn ": any" src/ --include='*.ts' --include='*.tsx'
grep -rn "console.log" src/ --include='*.ts' --exclude='*.test.*'
grep -rn "except Exception" . --include='*.py'
Each hit is a session that got past your current config. That gap
between what your rules forbid and what your codebase contains is the
whole argument for naming failure modes explicitly.
Top comments (0)