Case Study
← All articlesWe Ran a Static Analysis Tool on a Merged Open Source PR. Here Is What It Found.
Jellyfin PR #16062: 129 findings across 13 rules in 660ms. 11 were block-level issues that escaped code review.
Jellyfin PR #16062 is titled "Query Performance Improvements." It touched 126 files, added 27,810 lines, and removed 3,932. It was reviewed, approved, and merged on May 3, 2026.
We ran GauntletCI against the diff after it merged. In 660 milliseconds, it produced 129 findings across 13 rules. Eleven of those findings were block-level: the kind that should stop a merge.
Nobody caught them in code review. The tests passed. The PR shipped.
What GauntletCI Is
GauntletCI is a diff-first Behavioral Change Risk detector for .NET. It does not run tests. It does not compile code. It does not use a language model to evaluate your changes. It runs a set of deterministic rules against the diff and produces findings that are reproducible every time.
The same diff produces the same findings. Always.
It answers one question: did this change introduce behavior that is not properly validated?
The PR
Jellyfin is a free, open source media server written in .NET. PR #16062 was a significant refactor: query logic that previously ran in memory was moved to the database layer. The goal was performance. The change was substantial.
The kind of PR where things go wrong in ways that look fine on the surface.
What GauntletCI Found
Concurrency and State Risk
Five deadlock candidates: blocking calls on async operations (.Wait() and .GetAwaiter().GetResult())
Security Risk
Three dangerous API usages: Reflection and Activator.CreateInstance bypassing the DI container
Performance Hotpath Risk
Twenty-eight N+1 query patterns: LINQ queries executing inside loops
Dependency Injection Safety
Forty-five service locator anti-patterns: reaching into the DI container instead of declaring dependencies
Nullability and Type Safety
Fifteen as-cast operations without null checks
Edge Case Handling
Thirteen .Value accesses on nullable types without preceding null checks
What the Numbers Mean
129 findings. 11 block-level. 660 milliseconds.
The PR had human reviewers. It had automated tests. It passed both. It merged.
GauntletCI does not replace reviewers or tests. Reviewers check intent. Tests check known behavior. GauntletCI checks something different: whether the behavioral impact of the change is verified.
A reviewer looking at a LINQ query inside a loop in a 27,000-line diff might not recognize it as a performance regression. A test suite that was written against the old in-memory behavior will not catch a behavioral shift when the logic moves to the database layer. GauntletCI looks at the diff and asks whether the change introduced patterns that are structurally risky, regardless of whether the tests pass.
That is the gap it fills. Not better tests. Not smarter reviewers. A different question asked at a different time.
Try It Yourself
The GauntletCI-Demo repo contains six always-open scenario PRs against a realistic ASP.NET Core OrderService. Each one buries a single risky change in a plausible multi-file diff. GauntletCI runs on every PR: you can read the workflow output without installing anything.
If you want to run it locally:
dotnet tool install -g GauntletCI
gauntletci analyze --stagedNo configuration required. No code leaves your machine. No LLM in the detection path.
If you want to catch the kind of issues described in this post before they merge rather than after, that is the point.
One More Thing
If you work on or contribute to Jellyfin: this analysis was performed against the public diff of PR #16062 as an independent validation exercise. The findings are documented and reproducible. The diff is public. Anyone can verify them.
The intent is not to criticize the Jellyfin team. A PR of this size and complexity, touching core data access paths across 126 files, is exactly the kind of change where this class of issue is hardest to catch in review. That is the point.
