Skip to content

Blog · June 5, 2026 · 6 min read · by Codritium Editorial

The 12 Most Common Bugs AI Pair Programmers Introduce

A taxonomy of the bugs AI pair programmers introduce most often in production codebases — with the patterns, the failure modes, and how reviewers catch them.

debugging
ai-pair-programming
listicle

AI pair programmers fail in patterns. Across 1,876 AI-introduced defects we tracked in our 2026 benchmark, twelve bug classes covered 96% of cases. The remaining 4% was a long tail of one-offs. The twelve are not exotic. Most are bugs experienced engineers would catch in five seconds of review — if they were looking. The point of this taxonomy is to put each pattern in front of the next reviewer before they miss it.

Why this matters

Every team running AI pair tooling has a regression-rate story by now. Most of them sound the same: things were faster, then something shipped that shouldn't have, and now there's a review policy. The review policies tend to be vague — "look harder," "ask a question," "use your judgment." None of that scales. What does scale is naming the failure modes specifically enough that a reviewer can pattern-match. Twelve named classes is short enough to memorize. The rest of this post walks each one.

Stale-context bugs (#1–#3)

These are the bugs where the AI is reasoning against an out-of-date picture of the code. The model's training data, or the local context window, has a version of a schema, a function signature, or a library API that no longer matches the codebase. The suggestion compiles in the AI's head; it does not compile or behave correctly in yours.

#1 — Stale schema is the largest single class in our taxonomy. The AI proposes a query against a column that was renamed, or asserts a JSON shape that was migrated. The code compiles when the type is loose and fails at runtime when it is strict. Caught by integration tests that bind to the real schema.

#2 — Stale library API covers the cases where the AI calls a function with the old signature, an old parameter order, or a default that was removed two minor versions ago. Common in TypeScript and Python with fast-moving SDKs. Caught by the type checker if you run a strict one and by deprecation warnings if you read them.

#3 — Stale internal function signature is the same failure inside your own codebase. The AI suggests a call against getUser(id) when the team refactored it to getUser({ id, scope }) last sprint. The model saw the old signature in its local context and confidently produced the wrong call. Caught by a clean local build.

#ClassModal languageModal areaShare6-quarter trend
1Stale schemaTypeScriptData layer12.3%
2Stale library APITypeScriptSDK adapters9.7%
3Stale internal signaturePythonRefactor zones7.8%
4Plausible-nonsense logicPythonBusiness logic9.4%
5Confident wrong constantPythonConfig / limits5.6%
6Hallucinated importPythonModule wiring4.8%
7Auth-boundary driftTypeScriptAPI handlers10.6%
8Silent error swallowGoError paths8.4%
9Off-by-one / rangeTypeScriptList handling7.1%
10Race / orderingGoConcurrency6.3%
11Resource leakJavaConnections / files5.0%
12Wrong API versionTypeScriptExternal calls4.1%
The twelve bug classes, ranked by share of total AI-introduced defects.Tracked across 4,200 paired sessions, 14 codebases, H1 2026. Directionally consistent with the underlying research piece; numbers differ because we added a quarter of new data.

Plausible-nonsense bugs (#4–#6)

These are the bugs the AI writes confidently, where the code reads cleanly, compiles cleanly, and is semantically wrong. They are the hardest class for a reviewer to catch because every cue says "this is a normal piece of code." The detection rate on this class is the lowest of the twelve.

#4 — Plausible-nonsense logic is the modal bug here. The AI writes a function that looks like it does what the comment says. The control flow is reasonable. The variables are named well. The logic is wrong — a comparison flipped, a conditional that misses an edge case, a transformation that loses a field. Python sees more of this than other languages because the language tolerates more loose typing, which gives plausible nonsense more places to hide. Caught by tests that exercise edge cases — which the AI also tends not to write.

#5 — Confident wrong constant covers cases where the AI fills in a value as if it knew one — a limit, a timeout, a magic number — and the value is wrong for your codebase. The model has seen a thousand codebases where MAX_RETRIES = 3 is fine; in yours, the upstream is rate-limited and three retries are an outage. Caught by reading every literal in a diff.

#6 — Hallucinated import is the bug where the AI imports a function or class that doesn't exist. Sometimes the name is a near-miss of a real function; sometimes it is invented whole. Most languages catch this at import time. Python with dynamic imports and TypeScript with declaration merging will sometimes let it through to a runtime error. Caught by a clean local build.

The twelve classes sized by raw count of AI-introduced defects in the H1 2026 tracked sample.n = 1,708 defects classified by panel; the long tail of 4% is not shown.

Boundary-drift bugs (#7–#9)

These are the bugs that move where work happens — the auth check that drifts into business logic, the input validation that drifts to the wrong layer, the index that drifts past the end of the array. They are about boundary conditions, and they are about the AI not knowing where the right boundary is.

#7 — Auth-boundary drift is the bug class with the highest regression cost in our taxonomy. The AI suggests a permission check inside a service method when the boundary is actually at the API handler one layer up. Or it suggests a check at the handler when the boundary is supposed to be at a middleware. The check executes; the bug is that it executes in the wrong place, and the right place is now empty. Caught by tests that exercise the boundary, not the inner method. This class is increasing — it has the steepest upward trend of any class in the taxonomy over the last six quarters.

#8 — Silent error swallow is the Go-flavoured version. The AI proposes an error-handling block that logs and continues when the right action is to surface and abort. The code reads like defensive programming. It is, in practice, a fault-suppression layer. Common in retry wrappers and adapter code. Caught by an explicit policy on which errors are fatal in which layers.

#9 — Off-by-one / range is the oldest class on this list and the one experienced engineers expect to catch. The AI proposes i < n when the bound should be i <= n, or slices an array with arr.slice(0, n+1) when the intent was slice(0, n). Modern AI is better at this than older models but still produces it at roughly 7% of all introduced defects. Caught by tests that exercise the boundary value and one-past-it.

Concurrency and resource bugs (#10–#12)

These are the bugs that show up under load, not in local testing. They are the class most likely to ship to production and reveal themselves only under traffic. Detection is hardest because reproduction is hardest.

#10 — Race / ordering covers the cases where the AI proposes concurrent code that is correct under serial execution and wrong when the two paths interleave. Common in event-loop code and Go goroutines. The AI tends to write the optimistic path well and the contention path badly. Caught by stress tests with deliberate scheduling jitter.

#11 — Resource leak is the bug where the AI proposes opening a connection, file handle, or context without a matching close. The code looks complete. The leak shows up after an hour of traffic. Common in Java and in Python where the AI proposes raw resource acquisition instead of a context manager. Caught by resource-usage monitoring in load tests.

#12 — Wrong API version is the class where the AI calls an external service with the wrong endpoint path or schema. Distinct from stale library API because the failure surface is the network, not the build. The AI knows API v1 perfectly; the codebase has migrated to v2. Caught by integration tests against the real upstream — which most teams don't run on every PR.

How do you actually decide whether to accept a suggestion?

The honest mitigation for every bug above is not "use a better model." It is "read the suggestion before you accept it." The decision tree below is the one engineers in our top-quartile cohort report using by default. It is not subtle. It has three branches and the answer at every leaf is a verb.

Can I articulate why this suggestion is right?
No
Ask the AI to explain its reasoning, then re-read.
Now can I?
Accept, with a comment naming the why.
Still no?
Reject. Re-prompt with a tighter spec.
Yes
Does the suggestion cross a boundary (auth, schema, API)?
No
Accept.
Yes
Run the boundary-specific test before accepting.
A three-question flow for deciding whether to accept an AI suggestion.The flow used by the top-quartile cohort in our 2026 tracked sample.

Common questions

  • Why does AI introduce these specific patterns?

    Because the patterns reflect how models reason from training data and local context. Stale-context bugs come from training-data drift; plausible-nonsense bugs come from optimizing for token plausibility; boundary-drift bugs come from the model not having a stable map of your codebase's layering. The taxonomy is a map of the mechanism, not just the symptom.

  • Does this happen with every AI tool?

    Yes, with different shares. Tools with stronger codebase context produce fewer stale-context bugs and slightly more boundary-drift bugs (they look further afield for an answer and sometimes land in the wrong layer). Tools with weaker context produce more hallucinated imports. The total share of AI-introduced defects is similar across tools we tested.

  • How can I catch these in code review?

    Memorize the top five patterns from the data table and check every AI-touched diff against them in order. The combined detection rate for a reviewer who knows the five is materially higher than for one who reviews blind. The decision tree above is the simpler version of the same idea.

  • Which is the worst class to ship?

    Auth-boundary drift. Its regression cost is the highest of the twelve because it tends to fail silently — the request succeeds, the data is exposed, and the bug is only visible from outside the system. Plausible-nonsense logic is a close second because detection is slow.

  • Do these bugs increase over time?

    Some do, some don't. Auth-boundary drift is rising steadily in our six-quarter trend. Hallucinated imports are falling as model context windows grow. Off-by-one is roughly flat. The trend column in the table shows the directional sparkline for each class.

Where to go next