I spend over $135 a month on AI coding tools. I use them every single day. They have genuinely made me more productive. And there are still entire categories of work where I have learned to not even bother asking the AI, because it wastes more time than it saves.
This is not a “AI is overhyped” rant. I am a daily power user who loves these tools. But I think the conversation around AI coding is dangerously one-sided. Everyone shares their wins. Nobody talks about the three hours they spent debugging an AI-introduced bug, or the architecture suggestion that led to a two-week rewrite.
Here are nine things AI coding tools are still genuinely terrible at in July 2026, and what this means for how you should actually use them.
1. Architecture Decisions
This is the big one. AI will confidently suggest architectural patterns. It will give you diagrams, explain tradeoffs, recommend specific approaches. And it will be wrong in ways that are expensive to discover.
The problem is fundamental: architecture decisions depend on constraints that the AI cannot see. Your team size. Your deployment environment. Your growth trajectory. Your existing technical debt. The political dynamics of which team owns which service. The fact that your database is hosted in a region with 200ms latency to your primary users.
I asked Claude Code to suggest an architecture for a new notification service. It recommended an event-driven microservice with a message queue. Textbook correct. Looks great in a blog post. But my team was three people, we already had 12 services, and what we actually needed was a simple module inside our existing API. The AI optimized for theoretical correctness instead of practical reality.
I learned this lesson the hard way and described it in my first-year AI mistakes article. Two weeks of work thrown away because I followed AI architecture advice without questioning it.
What to do instead: Use AI to explain architectural patterns, list tradeoffs, and generate implementation details once you have made the decision. Never let it make the decision for you.
2. Naming Things
Phil Karlton’s famous quote holds up. Naming things remains hard, and AI makes it harder in a subtle way: it gives you names that are technically descriptive but lack the semantic richness that makes code readable.
AI-generated names fall into two failure modes:
Too generic: data, result, items, response, handler, processor. These tell you nothing about what the variable actually represents in your domain.
Too verbose: processedUserAuthenticationTokenFromOAuthProvider, validateAndTransformIncomingWebhookPayload. These are technically accurate but make your code read like a legal document.
Good naming requires understanding the domain deeply enough to pick the word that communicates the most with the least characters. AI picks the safest word that could not be wrong, which is different from the best word.
I now treat every AI-generated name as a placeholder to be replaced during review. It is faster to rename things after generation than to prompt the AI repeatedly for better names.
3. Business Logic That Lives in People’s Heads
Every codebase has implicit business rules that are not written down anywhere. They exist in Slack conversations, meeting recordings, the PM’s memory, and “that’s just how we’ve always done it.”
AI cannot access any of this. So when you ask it to implement a feature, it will implement the obvious interpretation of your prompt, not the correct interpretation that accounts for the seventeen edge cases your team discovered over the past year.
Example: “Implement a function that calculates a user’s subscription renewal date.” Simple, right? Except in our system: enterprise users get a 15-day grace period, monthly users who cancel retain access until the period end, annual users get prorated refunds only if they cancel in the first 30 days, and users who were on a legacy plan have completely different logic.
The AI will give you a clean, simple implementation that handles none of this. And if you do not catch it, you ship incorrect billing logic.
This is why Claude Code works better than simpler tools for business logic: you can feed it extensive context about the domain. But even with perfect context, it still misses the things that are not documented anywhere.
4. Working with Legacy Code
AI models were trained on modern code. They suggest modern patterns. This is usually fine, but when you are working on a codebase that was started in 2015 and has layers of legacy decisions, the AI’s suggestions can be actively harmful.
I asked an AI to fix a bug in a Node.js service that used callbacks (not async/await). The AI “fixed” the bug by rewriting the function to use async/await. This worked in isolation but broke the error handling contract that the rest of the module expected. The callback-based pattern was intentional because the calling code relied on specific error propagation behavior that async/await handles differently.
Modern patterns are not always better when they conflict with the assumptions baked into surrounding code. AI does not understand these implicit contracts.
For legacy codebases, I have found that Aider can be useful because you can give it very specific, constrained instructions: “Fix this bug without changing the function signature or async pattern.” But you have to know to add those constraints yourself.
5. Performance-Aware Code
AI writes correct code. It almost never writes fast code.
The pattern I see repeatedly: AI generates an implementation that passes all tests but has O(n^2) complexity where O(n) was straightforward. It creates arrays when Sets would be appropriate. It does unnecessary copies. It makes database queries inside loops. It reaches for .filter().map().reduce() chains that iterate the array three times when a single loop would do.
This is not a catastrophe for most applications. But if you are working on anything performance-sensitive (real-time systems, data processing pipelines, high-traffic APIs), you need to treat AI output with suspicion regarding performance.
I found one Claude Code refactoring that introduced 12 unnecessary array copies in a hot path. Each copy was individually harmless, but together they increased memory allocation by 3x in a function that ran thousands of times per second. The tests all passed. The code was more “readable.” It was also unacceptably slow.
What to do: Review AI output specifically for performance patterns. Run benchmarks on critical paths. Do not assume “correct” means “fast.”
6. Security Beyond the Happy Path
AI is decent at the basic security stuff: parameterized queries, input validation, CORS headers, bcrypt for passwords. It has seen enough security tutorials to get the textbook patterns right.
Where it fails: the edge cases that real attackers exploit. Timing attacks on authentication. SSRF via redirect chains. Race conditions in authorization checks. Mass assignment vulnerabilities where the AI helpfully accepts all user-provided fields. JWT validation that checks the signature but not the issuer or expiration in certain edge cases.
I had an AI-generated endpoint that properly validated input but failed to check authorization for a specific edge case: when a user was accessing their own resource through a team-shared URL. The happy path was secure. The edge case was not. It took a security review to catch it.
You cannot outsource security thinking to AI. Use it to generate the boilerplate security patterns, but always do manual security review on authentication, authorization, and data access boundaries. The best AI coding tools are getting better at this, but they are still not reliable enough to trust without human review.
7. Tests That Actually Test the Right Things
AI loves generating tests. It will happily produce 50 test cases for a function. And they will all pass. And many of them will not test anything meaningful.
The failure modes:
Testing the implementation, not the behavior: AI writes tests that assert on internal implementation details. When you refactor, all the tests break even though the behavior is unchanged.
Tautological tests: Tests that are basically expect(add(2, 3)).toBe(5) repeated with different values but never testing edge cases, error paths, or boundary conditions.
Missing the important cases: AI tests the happy path thoroughly but misses the critical edge case that your function was specifically designed to handle.
Mocking too aggressively: AI mocks everything, which makes tests pass in isolation but tells you nothing about whether your code works in the actual system.
I described the time I shipped bugs because of over-trusted AI tests in my first-year mistakes article. Now my rule is: AI generates the test scaffold, I write the actual assertions for critical logic.
8. Code Review at the Logic Level
AI code review tools are great at catching surface-level issues: style inconsistencies, missing error handling, potential null references, unused imports. They save significant time on the mechanical parts of code review.
But they consistently miss logic errors. The kind where the code does exactly what it says, but what it says is not what you intended. Off-by-one errors in business logic. Incorrect state machine transitions. Functions that handle 9 out of 10 cases correctly.
I use Claude Code for pre-review (which I describe in my time savings breakdown), but I have learned that the logic-level review still requires human eyes. If anything, AI review creates a false sense of security that makes humans less likely to do the deep reading.
9. Understanding When NOT to Write Code
This is the meta-problem. AI tools make it incredibly easy and fast to write code. They never say “you do not need this feature” or “this would be better solved by changing the process” or “have you considered just using a spreadsheet for this?”
Every prompt gets a code response. This creates a subtle bias toward solving problems with code even when a better solution exists. Configuration over code. Process changes over automation. Removing features over adding complexity.
I have caught myself implementing AI-suggested features that should not have existed. The AI will never push back on your premise. It will never say “this is a bad idea.” It will always give you a beautiful, well-tested implementation of something that should not be built.
What This Means for How You Should Use AI Tools
The pattern across all nine failures is the same: AI excels at implementation and fails at judgment. It can write the code brilliantly but cannot decide what code to write.
This means the highest-value use of AI tools is:
- You decide what to build (architecture, design, feature scope)
- You decide what matters (edge cases, performance requirements, security model)
- AI implements it (writing the actual code, fast)
- You verify it (review for the things AI misses)
The developers I see struggling with AI tools are the ones trying to skip steps 1, 2, and 4. They want AI to be the entire brain. It cannot be. It is a very fast pair of hands that need a human brain directing them.
For building an effective stack that works within these limitations, check my best AI coding tools guide. For reducing the cost of using AI within its actual strengths, see my LLM cost reduction strategies.
The tools will improve. Opus 5 is significantly better at reasoning than what we had a year ago. DeepSeek V4 punches above its price point. But the fundamental limitation (judgment requires context that AI does not have) is not going away soon.
Use AI for what it is good at. Do not abdicate the things it is bad at. That is the recipe for actually getting 10x value instead of 10x bugs.
FAQ
Will these limitations improve with future models?
Some will. Performance awareness is a training data problem that will get better. Business logic understanding is a context problem that larger windows partially solve. But architecture judgment and the “when not to code” problem are fundamentally about understanding constraints that exist outside the codebase. I do not see those being solved by larger models alone.
Should these limitations make me use AI tools less?
No. They should make you use AI tools more precisely. Knowing the boundaries means you can lean heavily on AI within those boundaries (boilerplate, debugging, refactoring, documentation) and not waste time asking for things it cannot deliver (architecture, naming, security review). Both overuse and underuse are mistakes.
Does providing more context fix the business logic problem?
Partially. I have had success giving Claude Code extensive documentation about business rules before asking it to implement logic. It works maybe 70% of the time for well-documented rules. But the dangerous cases are always the undocumented rules, the ones you do not think to mention because they are “obvious” to anyone on the team.
Are some tools better than others at these problem areas?
Yes. Claude Code with Opus 5 is the best I have used at reasoning about complex logic. It still fails, but less often than cheaper models. For security review, specialized tools like Snyk are still better than general-purpose AI. For performance, nothing replaces actual profiling. I cover tool-specific strengths in my local-first developer stack and fifty-dollar stack guides.
Is AI-generated code lower quality than human-written code?
On average, no. It is roughly equivalent in quality to a competent mid-level developer writing quickly. The difference is that a human knows what they do not know, and AI does not. A human will pause and think “wait, what about the edge case where…” The AI just confidently writes the edge case wrong. The quality is similar; the error awareness is not.