DEV Community

michael smith
michael smith

Posted on

5 code smells I keep finding in AI written codebases

I spend most of my days thinking about code health. Lately, a growing share of the code I look at was written by an AI and approved by a human who skimmed it at best. After enough repos, the same problems show up so often that I can spot them within seconds. Here are the five I see most, why each one happens, and the practical fix I reach for every time.

1. The same helper, written three times

Ask your AI for a date formatter on Monday and a slightly different one on Tuesday, and you will get two near identical functions living in two different files. Models are lazy about abstraction. They would rather paste a fresh copy than hunt down the existing one and reuse it. Studies of enterprise repos have reported duplication climbing sharply since AI assistance went mainstream, with one analysis putting the increase at nearly eight times.

The cost shows up later. A bug in the logic now lives in three places. A behavior change means three edits. Nobody remembers all three exist.

The fix is boring and it works. The moment you spot the second copy, stop and extract the shared version. Give it a clear name, put it where the whole codebase can reach it, and delete the copies. Ten minutes now saves a week of archaeology later.

2. Three ways to do the same thing

One module validates input with a library. Another hand rolls its own checks with regex. A third skips validation entirely because the demo never sends bad input. Same story with error handling, logging, and state management. Small differences in how you phrase a prompt produce different solutions to identical problems, and over weeks the codebase fills with parallel approaches to the same concerns.

This is the one that hurts teams the most, because every new contributor has to learn three systems instead of one.

The fix: pick one approach per concern and write it down. A short conventions note in your repo, even just a paragraph per topic, beats a thousand lines of drift. Then tell the AI about it. Paste the conventions into your prompt or your agent instructions. Models follow written standards surprisingly well when you actually give them some.

3. The happy path, and nothing else

AI generated code adores the sunny day scenario. The form submits. The API returns 200. The payment succeeds. Everyone claps. Now ask what happens when the network drops halfway through the request, the API returns a shape nobody expected, or the user double clicks the submit button. Silence. The unhappy paths are where production incidents live, and they are exactly what the model skips when you do not ask.

The fix: for every AI written function that touches the outside world, meaning networks, files, payments, or user input, ask one more question before you merge. What breaks here, and what should happen then? If the answer is not in the code, send it back. This single habit catches more real bugs than any linter I know.

4. Secrets in the frontend, auth as an afterthought

This is the scary one. Reports on AI built apps keep finding API keys sitting in frontend bundles and routes with no protection at all. One 2026 report that scanned thousands of AI built applications found nearly half exposed secrets in frontend code. The model will happily hardcode a key to make the demo work, because making the demo work is what you asked for.

Worse, auth logic is where AI confidence most exceeds AI competence. The code looks right. The login works. But the authorization check you assumed is there might not be, and you will not find out from the demo.

The fix has two parts. First, every secret lives in environment variables, never in committed code, no exceptions. Second, treat any AI generated auth code as guilty until proven innocent. Read it line by line. This is the one file you do not skim. If you only review one thing this week, make it this.

5. No tests, just vibes

Only a small fraction of AI built apps ship with meaningful test coverage. The demo works, so nobody writes the test. Then month three arrives, something breaks, and nobody understands the system well enough to fix it quickly. A fix that should take an afternoon turns into weeks of digging through code nobody wrote and nobody read.

The fix: make the AI write the tests too, but put the same care into the test prompt as the feature prompt. Tell it the edge cases you care about. Name the sad paths explicitly. A test you never read is better than no test at all, but a test written from your spec is better still. Future you, debugging at midnight, will be grateful.

Why I am building a score for this

None of this means AI coding is bad. It means the review step matters more than ever. The teams getting the most out of these tools treat the AI as an acceleration layer on top of real engineering habits, not a replacement for them. Speed plus judgment beats speed alone, every time.

I am building Code Sonar because I wanted a simple answer to one question: how healthy is this codebase, really? You connect a GitHub repo and run a scan. You get a code health score from 300 to 850, plus plain English findings that point to the exact file and line, tell you how severe each issue is, and estimate how long a fix should take. Free scans are coming soon. If you want in early, here is the waitlist: https://muse.ai/s/waitlist-page-zxc6q7xbxii91n

Top comments (0)