Back to blog

Engineering

False Positive Rates in AI Code Review: What We Learned

6 min read
Abstract signal versus noise visualization

The most common objection to automated code review tools is not about what they miss. It's about what they flag incorrectly. Engineers who've dealt with noisy lint configurations know the cost: when a tool produces too many false positives, developers learn to dismiss its output. The false positive problem kills tools not through dramatic failure but through gradual irrelevance.

When we built Mergegleam's review engine, we spent more time on false positive rate than on any other metric. Here is what we learned.

Why False Positives Happen in Code Analysis

A false positive in code review is a finding that a human reviewer would dismiss as not actionable. Understanding why they occur is the prerequisite for reducing them.

Context blindness. Most static analysis tools operate on a narrow window of code -- often a single function or file. They flag a pattern that is dangerous in general without knowing whether the specific instance in this codebase, at this call site, with this data flow, is actually dangerous. A generic null dereference rule flags every unguarded access, even the ones where the surrounding business logic makes null structurally impossible.

Pattern over-generalization. Rules that were written to catch real bugs in one codebase get packaged into general-purpose tools and applied everywhere. The rule makes sense in the original context. It produces noise in a different context with different conventions. The team either disables the rule (and loses its genuine value) or mutes it everywhere (and drowns out real findings).

Incomplete dataflow modeling. A tool that doesn't track data flow across function or module boundaries will flag conditions that look dangerous locally but are provably safe given the broader context. The reviewer sees the flag, understands why it's safe in this case, dismisses it, and starts dismissing related flags without reading them.

What We Measured in Early Access

During our early-access program across pilot teams, we tracked two metrics per finding: whether a reviewer marked it as dismissed without action, and whether a dismissed finding was later associated with a production incident.

The dismiss-without-action rate across the first four weeks was around 31%. That was too high. Digging into which categories drove the dismissals, we found three patterns:

Test code findings. Analysis that applied production code rules to test files flagged patterns that are intentional in tests -- no-op assertions, null assignments for testing null handling, intentionally thrown exceptions that are immediately caught. These were almost universally dismissed.

Configuration and seed data files. Hardcoded strings flagged as potential injection vectors in configuration files that are checked into source control and read-only at runtime. The file's role made the finding irrelevant; the tool didn't know the file's role.

Architectural conventions the tool didn't know about. In codebases with established patterns -- "errors from this library are always handled at the controller boundary" -- flagging unhandled errors inside the library layer generated noise because the handling was by design occurring elsewhere.

How We Brought the Rate Down

Reducing false positives required changes at multiple levels.

File role inference. Before applying any analysis, the review engine classifies files by role: production code, test code, configuration, migration scripts, seed data, generated code. Rules applied to each role are scoped appropriately. Test files get a separate, narrower rule set that excludes patterns intentional in testing contexts.

Confidence thresholds per finding category. Rather than applying a binary flag/no-flag decision, the system assigns a confidence score to each potential finding. Findings below a threshold for their category are suppressed rather than shown. The thresholds are calibrated per category based on observed dismiss rates. High-dismiss categories have higher suppression thresholds.

Codebase-pattern learning. For repositories that have been in use for multiple review cycles, the analysis adapts to observed conventions. If a pattern that would normally be flagged is present in 40+ places in the codebase without any recorded incidents, the system treats it as an established convention and suppresses new instances in the same pattern family.

After these changes, the dismiss-without-action rate dropped from 31% to around 8% for new repositories and under 5% for repositories after four weeks of review history. The findings that remain are the ones engineers actually act on.

The Metric That Matters More Than False Positive Rate

False positive rate is important, but it is not the right optimization target on its own. A tool with 0% false positives that also flags nothing has achieved the goal by the wrong method. The metric that matters is the ratio of actionable findings to total findings -- what fraction of the flags a reviewer sees are actually worth addressing.

That ratio determines whether engineers read the review output or dismiss it. A tool that engineers dismiss costs you more than a tool that says nothing, because the dismissed tool creates the false impression that automated review is running while providing no actual coverage. The most expensive false positive is not the one that wastes five seconds dismissing it -- it's the one that trains the team to stop reading the review output entirely.