[BUG] [platform::intellij] EDT Slow Operation Error in DiagnosticTools causing IDE freezes
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The Claude Code plugin triggers a "Slow operations are prohibited on EDT" error when collecting diagnostics. This causes IDE performance issues and stack trace errors in the logs. The error occurs in DiagnosticTools.java when the daemon code analyzer finishes and attempts to check if error analysis is complete on the Event Dispatch Thread (EDT).
What Should Happen?
The diagnostic collection should happen on a background thread to avoid blocking the UI thread. The plugin should use IntelliJ's ReadAction.nonBlocking() or similar background execution patterns to perform file system and indexing operations without freezing the IDE.
Error Messages/Logs
java.lang.Throwable: Slow operations are prohibited on EDT. See SlowOperations.assertSlowOperationsAreAllowed javadoc.
at com.intellij.openapi.diagnostic.Logger.error(Logger.java:375)
at com.intellij.util.SlowOperations.logError(SlowOperations.java:180)
at com.intellij.util.SlowOperations.assertSlowOperationsAreAllowed(SlowOperations.java:128)
at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexDataImpl.ensureIsUpToDate(WorkspaceFileIndexDataImpl.kt:232)
at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexDataImpl.getFileInfo(WorkspaceFileIndexDataImpl.kt:176)
at com.intellij.workspaceModel.core.fileIndex.impl.WorkspaceFileIndexImpl.getFileInfo(WorkspaceFileIndexImpl.kt:357)
at com.anthropic.code.plugin.mcp.tools.DiagnosticTools$addTools$1$1$1.daemonFinished(DiagnosticTools.kt:106)
at com.intellij.codeInsight.daemon.DaemonCodeAnalyzer$DaemonListener.daemonFinished(DaemonCodeAnalyzer.java:123)
Steps to Reproduce
- Install Claude Code plugin version 0.1.12-beta
- Open any Java/Kotlin project in IntelliJ IDEA
- Edit a file to trigger code analysis
- Wait for daemon analysis to complete
- Check IDE logs - the EDT slow operation error appears
- IDE may feel sluggish during diagnostic collection
Claude Model
None
Is this a regression?
I don't know
Last Working Version
0.1.12-beta
Claude Code Version
n/a
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
Suspected cause: The plugin calls java daemonCodeAnalyzer.isErrorAnalyzingFinished(psiFile) on EDT in the daemonFinished() callback, which triggers workspace file index updates (slow I/O operations)
Location: DiagnosticTools.kt line 106 (decompiled to DiagnosticTools.java line 204)
Impact: UI freezes, performance degradation during code analysis
Proposed Solution: Use ReadAction.nonBlocking() or ApplicationManager.getApplication().executeOnPooledThread() to move slow operations off EDT
// Instead of calling directly on EDT:
if (daemonCodeAnalyzer.isErrorAnalyzingFinished(psiFile)) {
// ... diagnostic collection
}
// Use background execution:
ReadAction.nonBlocking {
if (daemonCodeAnalyzer.isErrorAnalyzingFinished(psiFile)) {
computeDiagnostics()
} else emptyList()
}.withDocumentsCommitted(project)
.finishOnUiThread(ModalityState.defaultModalityState()) { diagnostics ->
// Process results on EDT
processDiagnostics(diagnostics)
}.submit(AppExecutorUtil.getAppExecutorService())
@hackyon-anthropic
9a10
> import com.intellij.concurrency.AppExecutorUtil;
11a13,14
> import com.intellij.openapi.application.ModalityState;
> import com.intellij.openapi.application.ReadAction;
28a32
> import java.util.Collections;
75a80
>
90a96
>
92c98
< ApplicationManager.getApplication().invokeAndWait(<undefinedtype>::invokeSuspend$lambda$1);
---
> ApplicationManager.getApplication().invokeAndWait(() -> invokeSuspend$lambda$1(callToolRequest, project, projectDir, result, mcpService));
128c134,138
< return (Continuation)(new <anonymous constructor>($completion));
---
> return (Continuation)(new Function2(value, $completion) {
> public final Object invokeSuspend(Object $result) {
> return this.invokeSuspend($result);
> }
> });
132c142
< return ((<undefinedtype>)this.create(p1, p2)).invokeSuspend(Unit.INSTANCE);
---
> return ((Function2)this.create(p1, p2)).invokeSuspend(Unit.INSTANCE);
159c169,173
< Function2 var3 = new <anonymous constructor>($completion);
---
> Function2 var3 = new Function2(value, $completion) {
> public final Object invokeSuspend(Object $result) {
> return this.invokeSuspend($result);
> }
> };
165c179
< return ((<undefinedtype>)this.create(p1, p2)).invokeSuspend(Unit.INSTANCE);
---
> return ((Function2)this.create(p1, p2)).invokeSuspend(Unit.INSTANCE);
174a189
>
187d201
< int var10 = 0;
201a216
>
204,217c219,231
< if (daemonCodeAnalyzer.isErrorAnalyzingFinished(psiFile)) {
< connection.disconnect();
< Document var10000 = psiFile.getFileDocument();
< Intrinsics.checkNotNullExpressionValue(var10000, "getFileDocument(...)");
< Document document = var10000;
< List diagnostics = (List)(new ArrayList());
< DaemonCodeAnalyzerEx.processHighlights(document, $project, HighlightSeverity.WEAK_WARNING, 0, document.getTextLength(), <undefinedtype>::daemonFinished$lambda$1);
< Json this_$iv = (Json)Json.Default;
< FileDiagnostic var7 = new FileDiagnostic;
< String var10002 = args.getUri();
< if (var10002 == null) {
< var10002 = file.getPath();
< Intrinsics.checkNotNullExpressionValue(var10002, "getPath(...)");
< var10002 = UtilsKt.pathToFileUri(var10002);
---
> // FIX: Move slow operation to background thread using ReadAction.nonBlocking
> ReadAction.nonBlocking(() -> {
> // This runs on background thread - safe for slow operations
> if (daemonCodeAnalyzer.isErrorAnalyzingFinished(psiFile)) {
> Document var10000 = psiFile.getFileDocument();
> Intrinsics.checkNotNullExpressionValue(var10000, "getFileDocument(...)");
> Document document = var10000;
>
> List<Diagnostic> diagnostics = new ArrayList<>();
> DaemonCodeAnalyzerEx.processHighlights(document, $project, HighlightSeverity.WEAK_WARNING, 0, document.getTextLength(),
> (info) -> daemonFinished$lambda$0(document, diagnostics, info));
>
> return diagnostics;
218a233,248
> return Collections.<Diagnostic>emptyList();
> })
> .withDocumentsCommitted($project)
> .finishOnUiThread(ModalityState.defaultModalityState(), (diagnostics) -> {
> // This runs on EDT - safe for UI operations
> try {
> connection.disconnect();
>
> Json this_$iv = (Json)Json.Default;
> FileDiagnostic var7 = new FileDiagnostic();
> String var10002 = args.getUri();
> if (var10002 == null) {
> var10002 = file.getPath();
> Intrinsics.checkNotNullExpressionValue(var10002, "getPath(...)");
> var10002 = UtilsKt.pathToFileUri(var10002);
> }
220,227c250,261
< var7.<init>(var10002, diagnostics);
< List value$iv = CollectionsKt.listOf(var7);
< int $i$f$encodeToString = 0;
< this_$iv.getSerializersModule();
< String results = this_$iv.encodeToString((SerializationStrategy)(new ArrayListSerializer(FileDiagnostic.Companion.serializer())), value$iv);
< $result.complete(new CallToolResult(CollectionsKt.listOf(new TextContent(results)), (Boolean)null, (JsonObject)null, 6, (DefaultConstructorMarker)null));
< }
<
---
> var7.setUri(var10002);
> var7.setDiagnostics(diagnostics);
> List value$iv = CollectionsKt.listOf(var7);
> int $i$f$encodeToString = 0;
> this_$iv.getSerializersModule();
> String results = this_$iv.encodeToString((SerializationStrategy)(new ArrayListSerializer(FileDiagnostic.Companion.serializer())), value$iv);
> $result.complete(new CallToolResult(CollectionsKt.listOf(new TextContent(results)), (Boolean)null, (JsonObject)null, 6, (DefaultConstructorMarker)null));
> } catch (Exception e) {
> $result.complete(new CallToolResult(CollectionsKt.listOf(new TextContent("Error processing diagnostics: " + e.getMessage())), (Boolean)null, (JsonObject)null, 6, (DefaultConstructorMarker)null));
> }
> })
> .submit(AppExecutorUtil.getAppExecutorService());
230c264
< private static final boolean daemonFinished$lambda$0(Document $document, List $diagnostics, HighlightInfo info) {
---
> private static final boolean daemonFinished$lambda$0(Document $document, List<Diagnostic> $diagnostics, HighlightInfo info) {
243d276
<
246,249d278
<
< private static final boolean daemonFinished$lambda$1(Function1 $tmp0, Object p0) {
< return (Boolean)$tmp0.invoke(p0);
< }
250a280
>
254c284
< $result.complete(new CallToolResult(CollectionsKt.listOf(new TextContent("Error getting diagnostics")), (Boolean)null, (JsonObject)null, 6, (DefaultConstructorMarker)null));
---
> $result.complete(new CallToolResult(CollectionsKt.listOf(new TextContent("Error getting diagnostics: " + var11.getMessage())), (Boolean)null, (JsonObject)null, 6, (DefaultConstructorMarker)null));
256d285
<
260a290
>
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
active