[BUG] [platform:intellij] NullPointerException in DiagnosticTools when HighlightInfo.getDescription() returns null

Status Fixed / completed
Maintainer reply ✓ Yes — hackyon-anthropic
Activity 8 comments · opened Sep 29, 2025 · closed Oct 23, 2025
💡 Likely answer: A maintainer (hackyon-anthropic, collaborator) responded on this thread — see the highlighted reply below.

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 IntelliJ plugin (version 0.1.11-beta) crashes with a NullPointerException when processing code diagnostics via the MCP getDiagnostics tool. The error occurs in DiagnosticTools.kt at line 128 when HighlightInfo.getDescription() returns null.

Stack trace:

java.lang.NullPointerException: getDescription(...) must not be null
at com.anthropic.code.plugin.mcp.tools.DiagnosticTools$addTools$1$1$1.daemonFinished$lambda$0(DiagnosticTools.kt:128)
at com.anthropic.code.plugin.mcp.tools.DiagnosticTools$addTools$1$1$1.daemonFinished$lambda$1(DiagnosticTools.kt:118)
at com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx.lambda$processHighlights$0(DaemonCodeAnalyzerEx.java:74)

The issue occurs because IntelliJ's HighlightInfo.getDescription() can legitimately return null for certain types of code highlights (structural highlighting, visual-only markers, etc.), but the plugin assumes it will always have a value.

What Should Happen?

The plugin should handle null descriptions gracefully by either:

  1. Skipping highlights that don't have descriptions, or
  2. Providing a default description like "<No description>"

This prevents crashes when processing diagnostics for files that contain highlights without textual descriptions.

Error Messages/Logs

java.lang.NullPointerException: getDescription(...) must not be null
	at com.anthropic.code.plugin.mcp.tools.DiagnosticTools$addTools$1$1$1.daemonFinished$lambda$0(DiagnosticTools.kt:128)
	at com.anthropic.code.plugin.mcp.tools.DiagnosticTools$addTools$1$1$1.daemonFinished$lambda$1(DiagnosticTools.kt:118)
	at com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx.lambda$processHighlights$0(DaemonCodeAnalyzerEx.java:74)
	at com.intellij.util.containers.ContainerUtil.process(ContainerUtil.java:847)
	at com.intellij.openapi.editor.impl.MarkupModelImpl.processRangeHighlightersOverlappingWith(MarkupModelImpl.java:286)
	at com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx.processHighlights(DaemonCodeAnalyzerEx.java:67)
	at com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx.processHighlights(DaemonCodeAnalyzerEx.java:51)
	at com.anthropic.code.plugin.mcp.tools.DiagnosticTools$addTools$1$1$1.daemonFinished(DiagnosticTools.kt:112)
	at com.intellij.codeInsight.daemon.DaemonCodeAnalyzer$DaemonListener.daemonFinished(DaemonCodeAnalyzer.java:123)
	at com.intellij.util.messages.impl.MessageBusImplKt.invokeMethod(MessageBusImpl.kt:820)
	at com.intellij.util.messages.impl.MessageBusImplKt.invokeListener(MessageBusImpl.kt:764)
	at com.intellij.util.messages.impl.MessageBusImplKt.executeOrAddToQueue(MessageBusImpl.kt:585)
	at com.intellij.util.messages.impl.MessagePublisher.publish$intellij_platform_core(MessageBusImpl.kt:556)
	at com.intellij.util.messages.impl.MessagePublisher.invoke(MessageBusImpl.kt:533)
	at jdk.proxy2/jdk.proxy2.$Proxy86.daemonFinished(Unknown Source)
	at com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl$MyDaemonProgressIndicator.onStop(DaemonCodeAnalyzerImpl.java:1681)
	at com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator.stop(DaemonProgressIndicator.java:39)
	at com.intellij.codeInsight.daemon.impl.PassExecutorService.lambda$applyInformationToEditorsLater$3(PassExecutorService.java:554)
	at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:239)
	at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:25)
	at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:201)
	at com.intellij.openapi.application.impl.AppImplKt$runnableUnitFunction$1.invoke(appImpl.kt:124)
	at com.intellij.openapi.application.impl.AppImplKt$runnableUnitFunction$1.invoke(appImpl.kt:124)
	at com.intellij.platform.locking.impl.NestedLocksThreadingSupport.doRunWriteIntentReadAction(NestedLocksThreadingSupport.kt:717)
	at com.intellij.platform.locking.impl.NestedLocksThreadingSupport.runPreventiveWriteIntentReadAction(NestedLocksThreadingSupport.kt:691)
	at com.intellij.platform.locking.impl.NestedLocksThreadingSupport.runWriteIntentReadAction(NestedLocksThreadingSupport.kt:645)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:1053)
	at com.intellij.openapi.application.impl.ApplicationImpl$6.lambda$run$0(ApplicationImpl.java:601)
	at com.intellij.concurrency.ThreadContext.installThreadContext(threadContext.kt:305)
	at com.intellij.openapi.application.impl.ApplicationImpl$6.run(ApplicationImpl.java:600)
	at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
	at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:167)
	at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:173)
	at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:167)
	at com.intellij.util.concurrency.ContextRunnable.lambda$run$0(ContextRunnable.java:26)
	at com.intellij.concurrency.ThreadContext.resetThreadContext(threadContext.kt:294)
	at com.intellij.util.concurrency.ContextRunnable.run(ContextRunnable.java:25)
	at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:122)
	at com.intellij.openapi.application.impl.FlushQueue.lambda$flushNow$0(FlushQueue.java:42)
	at com.intellij.concurrency.ThreadContext.resetThreadContext(threadContext.kt:294)
	at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:30)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:781)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:728)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:750)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:660)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:513)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$0$0$0$0(IdeEventQueue.kt:333)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:896)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$0$0$0(IdeEventQueue.kt:332)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:1061)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:109)
	at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1061)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$0(IdeEventQueue.kt:327)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:367)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)

Steps to Reproduce

N/A

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.0

Platform

Claude Code Beta Intellij

Operating System

Other Linux

Terminal/Shell

IntelliJ IDEA terminal

Additional Information

_No response_

View original on GitHub ↗

8 Comments

hackyon-anthropic collaborator · 11 months ago

Is this happening a lot, or just occasionally? I'm expecting this to be a bug in the IntelliJ API, but I'll look into a way to handle this gracefully.

coleleavitt · 11 months ago
Is this happening a lot, or just occasionally? I'm expecting this to be a bug in the IntelliJ API, but I'll look into a way to handle this gracefully.

it's happening often I just decompiled and I'll provide what I was able to match it to

github-actions[bot] · 11 months ago

Found 2 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/4605
  2. https://github.com/anthropics/claude-code/issues/3085

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

coleleavitt · 11 months ago

those duplicate issues are of the same stacktrace but don't reference the bug where it persists: https://github.com/anthropics/claude-code/issues/4605

The issue

around line 128 in DiagnosticTools.kt:

DaemonCodeAnalyzerEx.processHighlights(document, $project, HighlightSeverity.WEAK_WARNING, 
    0, document.getTextLength(), <undefinedtype>::daemonFinished$lambda$1);
private static final boolean daemonFinished$lambda$0(Document $document, List $diagnostics, HighlightInfo info) {
    int lineStart = $document.getLineNumber(info.startOffset);
    int columnStart = info.startOffset - $document.getLineStartOffset(lineStart);
    int lineEnd = $document.getLineNumber(info.endOffset);
    int columnEnd = info.endOffset - $document.getLineStartOffset(lineEnd);
    
    // BUG: This line assumes getDescription() is never null
    String var10003 = info.getDescription();
    Intrinsics.checkNotNullExpressionValue(var10003, "getDescription(...)");
    
}

Pseudo Fix

override fun daemonFinished() {
    if (daemonCodeAnalyzer.isErrorAnalyzingFinished(psiFile)) {
        connection.disconnect()
        val document = psiFile.fileDocument
        val diagnostics = mutableListOf<Diagnostic>()
        
        DaemonCodeAnalyzerEx.processHighlights(
            document,
            project,
            HighlightSeverity.WEAK_WARNING,  // Includes TEXT_ATTRIBUTES (visual-only, no description)
            0,
            document.textLength
        ) { info ->
            val lineStart = document.getLineNumber(info.startOffset)
            val columnStart = info.startOffset - document.getLineStartOffset(lineStart)
            val lineEnd = document.getLineNumber(info.endOffset)
            val columnEnd = info.endOffset - document.getLineStartOffset(lineEnd)
            
            // FIX: Skip highlights without descriptions
            // Some highlights are visual-only (e.g., TEXT_ATTRIBUTES severity)
            // or created via newSilentAnnotation() with no message
            val description = info.description ?: return@processHighlights true
            
            diagnostics.add(
                Diagnostic(
                    message = description,
                    severity = Severity.from(info.severity.name),
                    range = CodeRange(
                        CursorPosition(lineStart, columnStart),
                        CursorPosition(lineEnd, columnEnd)
                    )
                )
            )
            true
        }
        
        // Serialize and return results
        val results = Json.encodeToString(listOf(FileDiagnostic(args.uri ?: file.path.toFileUri(), diagnostics)))
        result.complete(CallToolResult(listOf(TextContent(results))))
    }
}

Prop Explaination

The Claude Code plugin processes highlights starting from HighlightSeverity.WEAK_WARNING (value 200):

DaemonCodeAnalyzerEx.processHighlights(document, project, HighlightSeverity.WEAK_WARNING, 0, document.textLength)

But WEAK_WARNING is 200, which means it also includes:

TEXT_ATTRIBUTES (11) - visual-only

INFORMATION (10) - may be visual-only

Any custom severities between 11-200

Many of these highlights are intentionally created without descriptions because they're purely visual decorations.

https://github.com/JetBrains/intellij-community/blob/master/platform/analysis-api/src/com/intellij/codeInspection/InspectionProfileEntry.java

coleleavitt · 11 months ago
I'm expecting this to be a bug in the IntelliJ API, but I'll look into a way to handle this gracefully.

@hackyon-anthropic I should also mention this isn't a bug in the Intellij API, this is intended i.e.:
https://github.com/JetBrains/intellij-community/blob/master/platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.java

hackyon-anthropic collaborator · 11 months ago

Just submitted a fix! Looking into rolling out an update before end of week!

coleleavitt · 11 months ago
Just submitted a fix! Looking into rolling out an update before end of week!

Awesome! Thank you

github-actions[bot] · 10 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.