← All posts
·8 min read·DevReview Team

10 PR Review Mistakes AI Can Catch (That Humans Miss When They're Tired)

Even strong reviewers miss SQL injection patterns, missing timeouts, and goroutine leaks at 5pm on a Friday. Here are 10 categories where an AI second-pass earns its keep.

code-reviewbest-practicessecurity

Code review is supposed to catch bugs before they ship. In practice, it catches bugs *some of the time* — when the reviewer has slept, has the right context, and isn't trying to clear 11 PRs before EOD.

This isn't a knock on human reviewers. It's a structural problem: humans are great at architectural feedback and judgment calls. They're worse at *checklist work* — verifying that every database query in a 600-line diff uses parameterized arguments.

That's where AI code review earns its place: as a tireless first pass that handles the mechanical stuff, freeing humans for the interesting questions.

Here are 10 categories where we consistently see AI catch real issues that human reviewers missed.

1. SQL injection via string interpolation

The classic. F-strings in Python, template literals in JavaScript, format strings in Go — all of them make it tempting to build queries by concatenation. AI flags every f"SELECT ... {user_input}" and demands parameterization. Humans miss this when the variable name *looks* internal (user_id from JWT) but actually flowed through a request body somewhere.

2. Missing timeout on outbound HTTP

requests.post(url, json=payload) and fetch(url) will both hang forever if the remote server stops responding. In a synchronous worker, that's a single request stalling everything until the OS-level TCP timeout fires (often 2 hours). AI flags this every time. Humans flag it about 30% of the time.

3. Mutable default arguments in Python

def add_item(item, items=[]):
    items.append(item)
    return items

This is one of Python's most-copied bug patterns. The default [] is created once at function definition time, not per call. AI catches it instantly. Many human reviewers have seen it 1000 times and still miss it on PR #1001.

4. Goroutine leaks

Spawning a goroutine without a context.Context for cancellation, or without a wait mechanism, leaks. The function returns, the goroutine keeps running, and the test harness doesn't notice because tests are short. AI flags every go func() lacking either a ctx parameter or a sync.WaitGroup. Humans miss it because the bug only manifests at scale.

5. React hooks in conditionals

if (user) {
  const data = useQuery(['profile', user.id]);
}

This violates the Rules of Hooks and will produce wrong-component-state bugs. The React linter catches it *if you have it configured*. Many repos don't have eslint-plugin-react-hooks set up. AI catches it regardless of lint config.

6. Missing await before a Promise

async function save() {
  db.write(record);  // missing await
  return true;
}

The function returns true immediately, the write fires-and-forgets, and any error becomes an unhandled rejection. AI catches it from context (the function is async, the call returns a Promise). Humans miss it when the linter doesn't have @typescript-eslint/no-floating-promises enabled.

7. == token comparison (timing attacks)

if (token == expected) { /* ... */ }

In a security-sensitive context, this is vulnerable to timing attacks because string comparison short-circuits on the first mismatch. The fix is crypto.timingSafeEqual. AI flags this when the variable names hint at security context (token, signature, secret).

8. Stale useEffect dependencies

useEffect(() => {
  fetchUser(userId);
}, []);  // missing userId

The effect captures userId from the closure at first render and never updates. AI flags missing deps. Humans tend to assume // eslint-disable-next-line was intentional even when it wasn't.

9. Unbounded resource consumption

data = response.json()
for item in data:
    process(item)

What if data is a million items because the upstream API misbehaved? AI flags missing pagination, missing size limits, and missing streaming for endpoints that return user-controlled-size collections.

10. Bare except in Python

try:
    do_thing()
except:
    pass

Bare except swallows KeyboardInterrupt and SystemExit, which is almost never what you want. The fix is except Exception: (still broad, but at least Ctrl-C works). AI flags every bare except. Humans approve them because "the test passed."

The pattern

Notice what these have in common: they're all *checklist patterns* with well-known correct answers. AI is great at applying a 10,000-item checklist consistently. It's bad at telling you "this design won't scale" — that's the human reviewer's job.

Use both.


*If you want a concrete look at how DevReview catches these patterns, see How DevReview Works or start a free trial and run it against your own PRs.*

Try DevReview free

14-day trial · 5 free reviews/mo after that · No credit card required.

Start Free Trial