AI Code Smells: 15 Red Flags That Scream 'This Was Generated'

December 17th, 202516 min read

"Code Smell" is a classic term in software engineering. It refers to a surface indication that usually corresponds to a deeper problem in the system.

But in 2025, we have a new category: AI Code Smells.

These aren't necessarily bugs. They are patterns that indicate the code was generated by a probabilistic model rather than crafted by a human mind. They scream, "I don't really know what this code does, but statistically, this looks right."

The 15 Red Flags

1. The "Explicit" Boolean Check

AI models are often overly verbose to avoid ambiguity.

// AI Smell
if (user.isValid === true) { ... }

// Human
if (user.isValid) { ... }

2. The "Tutorial" Variable Names

Seeing `foo`, `bar`, or `baz` in production code? That's an LLM hallucinating a tutorial context.

3. The "Zombie" Code

Blocks of commented-out code that look like alternative implementations. AI often leaves its "drafts" behind.

4. The "One-Size-Fits-All" Error Log

Generic error handling that gives you zero context.

catch (error) {
  console.error("An error occurred:", error); // Thanks, helpful.
}

5. The "Regurgitated" Documentation

Comments that sound like they were copied straight from MDN.

// The map() method creates a new array populated with the results...
const newArray = array.map(...);

6. The "Over-Defensive" Null Check

Checking for existence three levels deep when the type system already guarantees it.

if (data && data.user && data.user.profile && data.user.profile.id) { ... }

7. The "Premature" Optimization

Implementing complex caching or memoization for a simple function that runs once.

8. The "Ghost" Variable

Variables that are declared, assigned, but never actually used. A sign of a refactor that the AI forgot to finish.

9. The "Copy-Paste" Repetition

Repeating the same logic 3 times instead of writing a loop or a helper function.

10. The "Over-Engineered" Class

Creating a `UserProcessor` class with a constructor and one method, instead of just a function.

11. The "Default" Switch Case

Handling a `default` case that throws an error, even when all enum values are covered.

12. The "Magic" Number

Using `86400000` directly in code instead of `const DAY_IN_MS = 86400000`.

13. The "Unused" Import

Importing `useEffect` but never using it. AI often hallucinates requirements.

14. The "Generic" TODO

`// TODO: Implement error handling` - The AI knows it should be there, but was too lazy to write it.

15. The "Soulless" Formatting

As always, the "Wall of Text" effect. No breathing room, no rhythm.

How to Refactor

If you spot these smells, don't just leave them. Refactor for Vibe.

  • Delete the obvious comments.
  • Flatten the nesting.
  • Rename variables to tell a story.
  • Remove the defensive code that you know isn't needed.

Smell Something Fishy?

Don't rely on your nose alone. Our detector uses 50+ heuristics to sniff out AI code smells instantly.

Sniff My Code →
Vibe Code Detector