Skip to content

Kotlin hover tests flaky: KLS NullPointerException when Gradle classpath resolution fails in CI #134

Description

@LakshyAAAgrawal

Problem

The Kotlin Language Server (KLS v1.3.13) intermittently throws a NullPointerException on textDocument/hover requests when it cannot resolve the project classpath via Gradle or Maven. This causes test_multilspy_kotlin_hover and test_multilspy_kotlin_sync_hover to fail non-deterministically in CI.

Failing tests:

Both tests are currently marked xfail(strict=False) in #133.

Root cause

On GitHub Actions runners, /usr/bin/gradle and /usr/bin/mvn exist but cannot be executed by the KLS Java process (error=13, Permission denied), even after sudo chmod a+x. The chmod fixes shell access but not JVM ProcessBuilder access — likely a runner security policy issue.

When classpath resolution fails, the KLS falls back to kotlinc stdlib only. With incomplete type information, hover requests on certain symbols trigger a NullPointerException inside the KLS:

Internal error: java.lang.NullPointerException
java.util.concurrent.CompletionException: java.lang.NullPointerException
    at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(Unknown Source)
    at java.base/java.util.concurrent.CompletableFuture.completeThrowable(Unknown Source)
    at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(Unknown Source)

This surfaces as multilspy.lsp_protocol_handler.server.Error: Internal error. (-32603).

Evidence that it's flaky (not consistent)

From CI run #24214120325:

  • Python 3.10: all Kotlin tests passed (both async and sync hover)
  • Python 3.14: all Kotlin tests passed
  • Python 3.12: async hover passed, sync hover failed

Same Gradle permission errors on all three, but the NullPointerException only triggers non-deterministically.

Possible fixes

  1. Upstream KLS fix: The KLS should handle missing classpath gracefully on hover instead of throwing NPE. This is a bug in fwcd/kotlin-language-server.
  2. Use a test repo that doesn't need Gradle: The current test repo is the KLS source itself (a Gradle project). A simpler Kotlin project with no build system dependency would avoid the classpath issue entirely.
  3. Runner-level fix: Figure out why JVM ProcessBuilder can't exec /usr/bin/gradle after chmod a+x on GitHub runners.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions