A few months back I approved a PR that was almost entirely AI-generated. It looked lovely — clean names, neat structure, tidy little helper functions, everything formated perfectly. I gave it a quick read, it all made sense, I clicked Approve. Two days later it broke in production on an empty input, something a five-line manual function would never have gotten wrong. That was my lesson: AI code reads better than it works, and reviewing it is genuinely a different skill. Let me share what I have learnt since.
If you want the general picture first, I wrote separately about code review in the AI era and the future of our job. This article is narrower and more hands-on: how do you actually review the code an AI wrote?
Why this is a different job
When you review a human’s code, you are partly reading their intent. The code is usually small, written to some plan, and the author can tell you exactly why line 40 is there. Even the bugs are honest — half-finished, messy, obviously unsure.
AI code is the opposite. It arrives large, polished, confidently formatted, with lovely variable names — but there is no human intent behind it. The model pattern-matched something plausible. And “plausible” is not “correct”. The really dangrous part is that it reads so cleanly that your eye just slides over it and clicks Approve. The AI is, in a sense, optimised to pass your review rather than to be right.
So the job flips. With human code you spend a lot of effort on style, readability, small mistakes. With AI code the formatter and linter already handle style — that is not where you should spend your attention. Your real job becomes two blunt questions: is this actually correct, and does it solve the real problem? Trust nothing, verify everything. Treat it like the output of a very fast, very confident junior who occasionally just makes things up — because that is exactly what it is.
Where AI code breaks — look hardest here
AI is brilliant at producing clean, plausible-looking code and consistently weak at the same handful of spots. So aim your limited review time straight at them.
- Edge cases. This is number one. AI writes beautiful happy-path code and quietly forgets empty lists, null, zero, negative numbers, huge inputs, unicode. Always ask: what are the inputs it did not handle?
- Error handling. Look for swallowed errors — a bare
except: pass, an ignored return value, a failure that is logged and then execution merrily continues as if nothing happened. - Security. AI happily reproduces insecure patterns from its training data: SQL built by string concatenation, secrets in the code, missing authorization checks,
evalon user input. The Security Engineering course has the full list, but review AI code with security glasses on. - Hallucinated APIs. The model will confidently call a method or pass a parameter that simply does not exist, or that existed in some old version. First question, always: does this code even run?
- Requirements fit. Did it solve your problem, or a slightly different nearby problem that it found easier? This is shockingly common. Read the actual task, then check the diff against it — not the other way round.
- The tests. Be very careful here. AI often writes tests that just assert whatever the (possibly buggy) code currently does — so they pass, but they test nothing. And they usually cover only the happy path. A green tick from AI-written tests means very little by itself.
- Concurrency, performance, codebase fit. Races and shared state (AI is weak at reasoning about these), N+1 queries and accidental O(n²), and the small stuff like ignoring your existing utility functions or pulling in a random new dependency for something trivial.
A six-step review flow
Here is the simple flow I follow now. In order, because the order matters.
- Does it solve the real problem? Read the task first, then the diff. Don’t let a beautiful diff distract you from the fact that it answered the wrong question.
- Run it — with YOUR tests. Not the AI’s happy-path tests. Write a few adversarial inputs yourself — the empty case, the huge case, the malformed case — and watch it fall over. This single step catches most of it.
- Read every line. The old rule, more important than ever: if you cannot explain why a line is there, you do not get to approve it. No skimming.
- Hunt the AI smells — the nine hotspots above. Go looking for them specifically; don’t wait to stumble on them.
- Do the tests actually test anything? Change the code to be deliberately wrong and see if a test fails. If nothing goes red, the tests are decoration.
- Does it fit the codebase? Conventions, existing helpers, no needless new dependencies, no reinventing something you already have.
One small trick that helps a lot: ask the AI to review its own code. “What edge cases does this miss? What could go wrong in production?” It is often surprisingly good at poking holes in its own work — but of course, you still verify what it says, because it can be confidently wrong about that too.
The real danger nobody prepared us for: the scaling trap
Here is the thing that actually worries me, more than any single bug. AI lets us generate code maybe ten times faster. But our ability to review code did not suddenly become ten times faster — a human still has to read and understand it, at human speed. If you let generation outrun review, you are not going faster; you are just shipping unreviewed code with extra steps, and the bugs pile up quicker than before.
So the fix is a bit counter-intuitive: slow down the merge, not the generation. Keep PRs small so they can actually be reviewed properly. Protect real review time. And agree on one simple team rule — nobody approves AI code they could not have written themselves and cannot explain. Because the moment you approve it, it is yours. You own it, at 2am, when it breaks. Review it like you will have to.
Takeaways
- AI code reads better than it works. Clean and confident is not the same as correct — don’t let a polished diff earn a rubber stamp.
- The job flips: the formatter handles style, so spend your review on “is it correct, and does it solve the real problem?” Trust nothing, verify everything.
- Look hardest at the AI weak spots: edge cases, error handling, security, hallucinated APIs, requirements fit, the tests, concurrency, performance, codebase fit.
- Follow the flow: real problem → run with YOUR tests → read every line → hunt the smells → check the tests test → check it fits.
- Mind the scaling trap: slow down the merge, not the generation. Never approve AI code you couldn’t have written and can’t explain — you own it either way.
More in this series: code review in the AI era, commits and pull requests, the big-picture future of software engineering, and the playbook to stay valuable. To sharpen the verification eye itself, the Security Engineering and System Design Masterclass courses are a good investment.









