The Developer's Guide to Reviewing AI-Generated Code
AI writes a growing share of every pull request. Here is how to review AI-generated code effectively — what to look for, what to trust, and when to rewrite.
Code review has always been about catching mistakes before they reach production. But when the code was written by an AI assistant rather than a human colleague, the dynamics of review change fundamentally. The mistakes the AI makes are different from the mistakes a human makes, and the things you need to check are not the same things you would check in a peer review.
This guide covers what experienced teams have learned about reviewing AI-generated code. It is organized by the categories of issues that AI models consistently produce, so you can run through a systematic checklist rather than relying on intuition developed for human-written code.
Why AI-generated code needs different review criteria
Human developers make mistakes that cluster around fatigue, distraction, and knowledge gaps — a tired developer misses an edge case, a distracted one forgets to handle an error, a junior one uses an anti-pattern because they do not know better. AI models make mistakes that cluster around entirely different axes: hallucination, context blindness, and stylistic inconsistency.
A human who writes a function that does not handle null inputs probably knows better and just forgot. An AI that writes the same function genuinely does not know whether null is possible in your codebase unless you explicitly told it. This distinction matters because the fix is different: a human needs a reminder, but the AI needs a constraint encoded in the prompt or caught in review.
Understanding this difference is the foundation of effective AI code review. You are not checking whether the developer was careful. You are checking whether the AI had enough context to produce correct code, and whether its output matches the implicit conventions of your codebase that it could not see.
Checklist item 1: Hallucinated APIs and imports
The single most common issue in AI-generated code is the use of libraries, functions, or APIs that do not exist. AI models are trained to produce plausible code, and they will confidently generate imports for packages that were never published and call methods that never existed. This is not malicious — it is the model interpolating between real packages it saw during training and inventing a bridge that looks reasonable.
// AI-generated code that looks plausible but imports a non-existent function
import { renderAsync } from 'react-dom'; // renderAsync does not exist
import { optimize } from 'lodash/fp/string'; // This path does not exist in lodash
// What you actually need
import { renderToString } from 'react-dom/server';The fix for this is simple but important: verify every import and every API call against actual documentation. Do not assume that because the code compiles, the APIs are correct — some hallucinated functions have reasonable-looking signatures that pass TypeScript checking but fail at runtime. The review should include a quick sanity check on any import you do not recognize.
Checklist item 2: Missing error handling
AI models tend to generate the happy path. They are remarkably good at writing the main logic of a function — the loop, the transformation, the return value — and remarkably bad at handling what happens when things go wrong. Network requests lack catch blocks. File operations lack error handling. Async functions lack rejection handlers.
This is not because the AI cannot write error handling. If you explicitly ask for it, the AI will produce thorough try-catch logic. The issue is that the default behavior of the model is to write the simplest working version, and error handling is not part of that default. Every AI-generated code review should include a pass that looks only at error paths.
- Every async function should have a catch or rejection handler.
- Every external API call should handle network errors, timeouts, and unexpected response formats.
- Every data transformation should handle null, undefined, and unexpected types.
- Every file or database operation should handle permission errors and missing resources.
A useful technique is to run a simple test: strip the try-catch blocks from the AI-generated code and see whether the remaining logic still makes sense. If it does, the AI probably did not think deeply about error handling. If the logic depends on the error handling to function, the AI integrated it properly.
Checklist item 3: Style and convention mismatches
Every codebase has unwritten style conventions. The team uses early returns, not nested ifs. Error messages follow a specific format. Variable names use a particular pattern. AI models trained on millions of public repositories will generate code that reflects the statistical average of all those repositories, not the specific conventions of your codebase.
The result is code that works but feels foreign. It uses a different naming convention, a different module structure, or a different error-handling pattern from the surrounding code. This kind of inconsistency accumulates quickly — five AI-generated functions written with five different implicit styles create a codebase that feels incoherent and is harder to maintain.
The best mitigation is to include style examples in your prompts. Paste a representative function from the same module and say use this style. This gives the AI a concrete reference that overrides its training default. During review, check that the generated code could have been written by the same person who wrote the surrounding module.
Checklist item 4: Over-engineering and unnecessary abstraction
AI models have a strong bias toward abstraction. Given a simple problem, they will often generate a class hierarchy, an interface, a factory, and three utility functions — where a single function would have sufficed. This tendency comes from the training data, which over-represents well-factored open-source libraries under-representing simple scripts and one-off functions.
AI models default to over-engineering. Your review should default to simplicity. Every abstraction the AI introduced needs to justify its existence against a simpler alternative.
During review, ask yourself: does this code need a class, or would a function work? Is this interface used by more than one implementation? Would extracting this utility save enough repetition to justify the indirection? If the answer to any of these is no, the AI probably over-engineered it, and the simpler version is better.
Checklist item 5: Security vulnerabilities
AI models are trained on code that contains security vulnerabilities. They learn patterns from that code, including the vulnerable ones. While modern models are better at avoiding obvious issues like SQL injection, they still produce code with subtle security problems that a reviewer needs to catch.
- Check for hardcoded secrets, API keys, or credentials in generated code.
- Verify that user input is validated and sanitized before use.
- Check that authentication and authorization checks are present on protected operations.
- Ensure that generated SQL queries use parameterized statements, not string concatenation.
- Verify that file paths are not constructed from untrusted input without sanitization.
A security-focused review pass is non-negotiable for AI-generated code that handles sensitive data or user input. The AI does not know which parts of your system are security-critical unless you tell it. When in doubt, run a static analysis tool over the generated code before merging.
Checklist item 6: Consistency with the existing architecture
AI models see each request in isolation. They do not know that your team agreed last quarter to use React Query for all data fetching, that the API always returns camelCase keys, or that the project uses a specific state management pattern. The code they generate will be internally consistent but may violate architectural decisions that are not visible in the current file.
This is where the human reviewer adds the most value. You know the decisions that are documented in your ADRs, the patterns that emerged from team discussions, and the design constraints that are not captured in any single file. Review AI-generated code against these invisible constraints, not just against correctness and style.
Building a sustainable review process
As AI generates more of your codebase, the review process needs to scale. A team of four reviewing every AI-generated line manually will burn out. The sustainable approach combines automated checks with focused human review.
Automated checks should catch hallucinated imports, style violations, missing error handling, and common security issues before a human ever sees the code. This reduces the AI-specific review to a smaller set of concerns: architectural consistency, design decisions, and the subtle problems that linters cannot detect.
The goal is not to eliminate human review of AI-generated code. It is to make that review as efficient as possible by filtering out the issues that tools can catch automatically and reserving human attention for the judgments that only humans can make. With the right process, reviewing AI-generated code becomes faster and more reliable than reviewing human-written code — because the AI's mistakes are more predictable.
