Engineering & Evidence
JetBrains Platform tickets
Bugs in JetBrains’ own code, documented publicly in JetBrains’ YouTrack tracker: six filed directly, four found in IntelliJ’s source by a check from this catalog or a related scan and two by measuring the Settings pages on the UI thread, plus root-cause analysis posted on existing IntelliJ Platform (IJPL) tickets, and two fixes sent as pull requests.
IDEA-393501 ↗
SearchForTestsTask: non-cancellable ReadAction.run() in a background task
Open
Found by Background ReadAction Freeze Companion. SearchForTestsTask is a Task.Backgroundable whose run() wraps search() in the cancellable ReadAction.nonBlocking(), then calls the sibling onFound() through the blocking ReadAction.run() a few lines later, with no checkCanceled() anywhere in the class. JetBrains’ Platform Blog names this pattern as a recurring cause of UI freezes. Filed as IJPL-254654; JetBrains moved it to the IDEA project (Java › Tests) and assigned it to a developer.
A follow-up comment (October 2026) added two points. The default smart-mode branch also blocks: it calls the deprecated DumbService.runReadActionInSmartMode(), which uses ReadAction.computeBlocking() internally. And a plain switch to ReadAction.nonBlocking() is not safe, because onFound() writes files and a restarted read action would write them again. Both calls are still on master as of October 2026.
IJPL-257836 ↗
DependenciesUsagesPanel.findUsages runs the whole dependency usage search in one non-cancellable read action
Open
Found by the same check as Background ReadAction Freeze Companion, run as a scan over IntelliJ’s own master. When a node is selected in the Dependency Viewer (Code › Analyze Code › Dependencies), DependenciesUsagesPanel.findUsages() analyzes every file of the selected scope inside one top-level ReadAction.runBlocking() on a pooled thread. A pending write action, such as typing in an editor, waits until the whole search ends. The ticket proposes the fix shape JetBrains used for IJPL-236316 (FindUsagesHelper): a non-blocking read action that no longer swallows ProcessCanceledException, with the UI update moved out of the read action. JetBrains support asked for reproduction steps. A headless test on a synthetic project reproduced it: with 2,000 files, a write action waited 4.8 s for the search, and 1 ms with a non-blocking read action. The test is attached to the ticket, and a fix is proposed in pull request #3684.
IJPL-257854 ↗
Auto-test: the error check of DelayedDocumentWatcher blocks typing until the whole check ends
Open
Found with the same check, during an audit of components that do background work after each edit. With auto-test enabled, DelayedDocumentWatcher waits for a typing pause and then checks every changed file for syntax errors (PsiErrorElementUtil.hasErrors()) in one blocking read action on a pooled thread. The keystroke that resumes typing waits for the whole check. Measured with the platform test framework on IntelliJ IDEA 2025.2: on a 50,000-line file, that keystroke took 436 ms with the current code, 48 ms without auto-test, and 73 ms with the check in a non-blocking read action. The measurement test is attached to the ticket, and a fix is proposed in pull request #3685.
IJPL-257908 ↗
Live Templates settings: isModified() checks every template against every context type on the EDT after each click or key press
Open
Found by measuring every Settings page on the UI thread of IntelliJ IDEA 2026.2.3 with the platform test framework. The Settings dialog calls isModified() of the open page about one second after each mouse click or key press. On the Live Templates page, that call compares all 1,295 templates against all 336 context types (TemplateContext.getDifference()), and the UI thread stops for about 165 ms each time. The ticket proposes a one-line check: two templates whose own context settings are equal cannot differ in any context type. In the same test, that check takes the comparison from 157 ms to 0 ms with the same result. The measurement test is attached to the ticket.
IJPL-257909 ↗
Settings | Plugins: isRequiredForEssentialPlugin rebuilds the plugin maps and walks all essential dependencies once per plugin on the EDT
Open
Found in the same measurement of the Settings pages. Opening Settings › Plugins builds the list of installed plugins on the UI thread and asks, for each plugin, whether an essential plugin requires it. Each answer builds the plugin and module maps again and walks the dependencies of every essential plugin; the source code already has a FIXME about it. With 158 plugins loaded, the page took 689–931 ms to open. One walk followed by a lookup per plugin took 8–22 ms and gave the same answer for every plugin. The cost grows with the square of the number of installed plugins. The measurement test is attached to the ticket.
IJPL-257919 ↗
Package File: PackageFileWorker does all the file I/O inside one blocking read action, so write actions wait for it
Submitted
Found by a scan of IntelliJ’s own master for slow work inside read actions, then measured. Build › Package File copies a file into the artifacts that contain it. PackageFileWorker finds those artifacts and then does all the file I/O inside the same blocking ReadAction.run(): the copy, opening the archive, and repacking a nested archive. A write action requested meanwhile, such as a key press, waits until the I/O ends. Measured with the platform test framework on IntelliJ IDEA 2026.2.3, with a WAR that contains a 40 MB JAR: the write action waited 2,219–2,508 ms. With only the artifact lookup in the read action and the I/O outside it, it waited 0 ms in 4 of 4 runs. The measurement test is attached to the ticket.
PR #3684 ↗
IJPL-257836 Dependency Viewer: run the usage search in a non-blocking read action
Open
Fix for IJPL-257836. The usage search runs in ReadAction.nonBlocking(...), which restarts when a write action is pending, the same fix shape JetBrains used for IJPL-236316. The search has no side effects, so a restart is safe, and the usage view is built after the read action. A new test holds the search inside its read action and checks that a write action does not wait for it. Against the IntelliJ IDEA 2025.2 jars, the write action waited 10,021 ms with the current code and 3 ms with the fix. The test was not run inside the full intellij-community build.
PR #3685 ↗
IJPL-257854 Auto-test: check changed files for errors in a non-blocking read action
Open
Fix for IJPL-257854. The error check runs in ReadAction.nonBlocking(...), which restarts when a write action is pending; hasErrors() has no side effects, so a restart is safe. The changed files are copied before the check, because the set is used on the EDT. Measured against the IntelliJ IDEA 2025.2 jars with a copy of the patched class: the keystroke that resumes typing on a 10,000-line file took 134 ms with the current code and 25 ms with the fix. The change was not built inside the full intellij-community build.
PR #3694 ↗
IJPL-257908 Live Templates: fast path in TemplateContext.getDifference
Open
Fix for IJPL-257908. Live Templates recomputed isModified() on the EDT after every click or keystroke (~165 ms on the measured setup). A one-line fast path in TemplateContext.getDifference brings that to ~0 ms. The equivalence is measured in a repro harness; the inspection test is run by JetBrains’ CI.
PR #3696 ↗
IJPL-257919 Package File: keep the file I/O outside the read action
Open
Fix for IJPL-257919. Build › Package File now resolves the target artifacts under a small ReadAction.compute(), but the file I/O (copying, opening and rewriting the ZIP, re-packing a nested archive) runs outside the read lock, so a write action no longer waits for it. The existing PackageFileActionTest covers the functional result; the timing measurement is attached to the ticket.
PR #3701 ↗
IJPL-257909 Plugins settings: cache the essential-plugin requirement set
Open
Fix for IJPL-257909. The Plugins settings page recomputed, for every plugin, whether it is required by an essential plugin (a FIXME in the source). The fix caches that set per PluginSet instance, invalidated structurally when the plugin set is replaced. Functional equivalence was reconfirmed across the catalog of descriptors (158/158).
PR #3697 ↗
IDEA-266545 New Java inspection: magnitude comparison of System.nanoTime()
Open
For IDEA-266545. A new Java inspection (Probable bugs, off by default) flags < > <= >= comparisons where an operand is a direct System.nanoTime() call; the correct subtraction idiom is not flagged. Detection logic verified locally against 2026.2.3; the inspection test runs in JetBrains’ CI.
PR #3698 ↗
IDEA-279282 Simplifiable Map operations: suggest map.remove(key, value)
Open
For IDEA-279282, an extension of the existing ‘Simplifiable Map operations’ inspection, where a JetBrains maintainer asked for it. It detects if (value.equals(map.get(key))) map.remove(key) (both operand orders) and offers map.remove(key, value), guarding against a null value and side-effecting key/value expressions.
PR #3699 ↗
IDEA-279659 New Java inspection: String.compareTo() used for equality
Open
For IDEA-279659. A new Java inspection (Verbose or redundant code, off by default) flags compareTo(...) == 0 / != 0 on strings and offers equals() / !equals(), restricted to String and guarded against the null-argument difference (compareTo(null) throws, equals(null) is false). Detection and quick-fix verified locally.
WorkspaceFileIndexDataImpl.fillPackageFilesAndDirectories() iterates an unsynchronized LinkedHashMap that can change mid-iteration, producing a ConcurrentModificationException. The analysis posted here located that iteration and proposed a ProgressManager.checkCanceled() call. JetBrains fixed the ticket on 2026-09-09 with a different change: the package-name queries now call ensureIsUpToDate() before reading, so the index is brought up to date first (commit e1d600df).
IJPL-27359 ↗
CME in InspectionToolRegistrar.createTools on loading/unloading plugins
Submitted
toolFactories is iterated as a live, unsynchronized view of a mutable map inside createTools(), running on background threads with no read-action lock, so a concurrent plugin unload can mutate the map mid-iteration. The same live view is still on master (now in Kotlin), so the 2020 failure looks reproducible under the same conditions.
IJPL-80817 ↗
Cannot create light service git4ide.repo.GitRepositoryManager because container is already disposed
Submitted
The original call site moved after a widget restructuring, but the repository lookup still runs under the deprecated runInReadActionWithWriteActionPriority, and none of the utility functions in the new chain (GitBranchUtil, DvcsUtil, GitUtil) call checkCanceled(), so a project closing can still race into an AlreadyDisposedException, with a narrower window than when it was reported.
IJPL-76141 ↗
Git Log is empty due to a StackOverflow exception in IntToIntBtree.processLeafPages
Open
processLeafPages recurses with no stack-depth guard, so a large enough index overflows the stack and silently empties Git Log. The same method fails in IJPL-250279, reported independently about a year later for the JPS build cache; the two tickets had not been linked. Proposed fix: rewrite the traversal iteratively.
IJPL-196254 ↗
Memory leak via ProjectRootManagerImpl::rootsChanged
Open
BatchSession's changes list only clears once its pendingRootsChanged counter hits exactly 0, but the counter is incremented without matching exception handling, so one exception or an asymmetric reentrant call can leave it stuck above 0 permanently, and changes then keeps growing on every later roots-changed event. The missing safety net is visible in the code; the exact first imbalance was not traced.
A comment with a headless reproduction of slow typing in large files. With the Structure tool window built for a Java file with 10,000 methods, the file holds 10,001 smart pointers, one per tree node (PsiTreeAnchorizer). After each keystroke the IDE restores every pointer: in IntelliJ IDEA 2026.2.3 a keystroke took a median of 1,080 ms, against 33 ms without the structure view, with 98% of the time in SmartPsiElementPointerImpl.doRestoreElement(). This matches the slow typing events reported in IJPL-173280. The test is attached to the comment.