In September 2025 and again in March 2026, JetBrains' own Platform engineering team published two posts about a specific, recurring cause of IntelliJ IDE freezes: a background thread calling a blocking, non-cancellable read-lock API (ReadAction.compute(), ReadAction.run(), Application#runReadAction()) while a write action is pending. The March post said it plainly:
"many reports actually show problems in plugins that contain that single erroneous pattern"
And just as plainly: there's no static tool that catches this today. Detection is manual — reading a thread dump after the freeze already happened in someone's real IDE.
That's a strange gap for a static-analysis catalog to walk past. So i didn't.
What i built — Background ReadAction Freeze Companion, a free, open-source IntelliJ Platform plugin that statically traces exactly this pattern. It's interprocedural — it walks the real call graph from four recognized background-thread entry points to a blocking read-lock call, however many method calls deep. It distinguishes the formally deprecated read-lock APIs from the one that isn't but is mechanically identical and explicitly discouraged in its own Javadoc. A hit where the surrounding code already checks for cancellation gets downgraded, not suppressed.
GitHub: https://github.com/GapHunterLabs/background-readaction-freeze-companion
Validating it against the real thing — i checked it out against intellij-community itself. First pass caught something for the right reason to not flag it: a real ReadAction.run() call in the Mercurial VCS integration that traces back to the EDT, not background — correctly held back. The same pass surfaced a real gap in our own coverage (a background entry point we hadn't covered yet); i added it the same day. Then, pointed at the Java test-execution module, it surfaced a clean, direct hit in SearchForTestsTask: nine lines apart, in the same method, one branch uses the cancellable pattern, the sibling branch — reachable through an ordinary "run tests before indexing finishes" interaction — uses the blocking one the Platform team's own post named.
I filed it: IJPL-254654, with the exact source reference and a suggested fix mirroring the pattern already used nine lines above it.
Why this, and why now — I read what a platform team said was a real, unsolved problem for them, built the tool that problem was asking for, and used it exactly the way it was designed — against real code, every finding hand-verified before it went anywhere.
Top comments (0)