You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Gradle multi-module project breaks on reload, requires cleaning Java Language Server workspace every time #4317
Description
I am working with a Java Gradle multi-module project in VS Code.
On the first load, the project fails with an error like:
The project was not built due to "xxx does not exist". Fix the problem, then try refreshing this project and building it since it may be inconsistent.
The suggested workaround is:
Disable Gradle for Java extension
Run "Java: Clean Java Language Server Workspace"
Reload the project
This workaround does fix the problem, but only temporarily.
Problem
Every time I:
reload the window, or
close and reopen the project
I have to run "Java: Clean Java Language Server Workspace" again, otherwise the same error appears.
This makes working with the project very inconvenient.
Expected behavior
Once the project is cleaned and loaded successfully:
It should stay in a consistent state
Reloading or reopening the project should not require cleaning the Java Language Server workspace again
Actual behavior
Project breaks again after reload
Same error repeats
Manual workspace cleaning is required every time
Environment
VS Code
Java multi-module Gradle project
Java Language Server
Gradle for Java extension enabled
Additional notes
This looks like a workspace cache or Gradle project import inconsistency issue.
It seems the Java Language Server does not correctly persist the resolved multi-module Gradle state across reloads.
changed the title [-]Java: Clean Java Language Server Workspace[/-][+]Gradle multi-module project breaks on reload, requires cleaning Java Language Server workspace every time[/+]on Jan 23, 2026
Hi @snjeza, thank you for the suggestions. I followed all the steps you mentioned, but the issue persists. Here is a summary of what I did and what I found:
Steps taken:
Added the following to both User settings and .vscode/settings.json:
However, I confirmed that none of my project's gradle-wrapper.properties files reference any snapshot distributions — all use gradle-9.1.0-bin.zip. I verified this with:
The result was empty. So these snapshot URLs appear to originate from JDT LS itself, not from my project.
Additionally, I am getting The import ***** cannot be resolved in the IDE, even though the cross-module dependency works fine at build time (./gradlew build succeeds). I migrated from project(':*****') with projectDir to Composite Build (includeBuild) with dependencySubstitution, but JDT LS still does not resolve the cross-directory module correctly.
Environment:
VS Code with redhat.java extension
JDT LS version: 1.57.0-SNAPSHOT
Gradle: 9.1.0
Java: 25
Multi-module Gradle project with cross-directory references
Is there a known workaround for JDT LS not resolving includeBuild composite builds across different directories? Any guidance would be appreciated.
Hey, I can reproduce something similar. After hours of narrowing down the problem, I can add some details here.
It looks like a closely related issue. In my case the problem specifically affects source navigation after Java: Reload Projects.
Environment
macOS arm64
VS Code Java extension stable: 1.55.0, also reproduced with pre-release: 1.56.2026081508
JDT LS running on Eclipse Temurin JDK 21
Projects compiled with Java 26
Gradle multi-project build using direct project dependencies, e.g.:
Both subproject and rootproject are correctly shown as separate projects under JAVA PROJECTS, and Java: List All Java Source Paths correctly lists subproject/src/main/java.
Reproducer
Starting from a working workspace:
./gradlew clean
After this, Go to Definition correctly navigates to:
During Java: Reload Projects, JDT LS then updates the classpaths for the complete multi-project build, including:
Updating classpath for project: subproject
Updating classpath for project: rootproject
...
This appears to be the point where the existing Gradle project dependency/source relationship gets replaced or shadowed by the binary output directory:
subproject/build/classes/java/main
Afterward, JDT resolves Main as a class file rather than:
Can anybody remember when this last worked properly? I wonder if we can narrow down an extension version to revert back to, assuming it's actually an extension issue...
I analyzed for hours (learnt a lot) to find the reason:
1.50.0 the problem can be reproduced based on the sequence
1.55.0 the problem can be reproduced based on the sequence
SOLUTION -> 1.56.2026082811 works now!
TL;DR:
The problem occurs only, if I open the source of a class that is inside the subproject. If "Go to Definition" inside the root project, the navigation works.
If I delete the exact class in the "build/classes/com/.../Main.class" inside the subproject, the "Go to Definition" works immediately (maybe it does a refresh in the background because of the filesystem trigger). If I "Reload Projects" it does create a "build" directory again, but with no classes. If i "Clean java Server Workspace" now, "Go to Definition" works and "build" directory still empty. If I call ./gradlew :subproject:compileJava the classes are created as expected. "Go to Definition" works. If I "Reload Projects" -> "Go to Definition" not working anymore. "Java: List all Java source paths" shows all paths to the subprojects source files. These are correct.
I investigated this further for hours using "Extension Dev Host" and found a concrete root cause that matches this behavior:
The problem is in the older JDT-LS Scala/Gradle classpath handling. During a Gradle project reload, javals.gradle treated artifacts produced by sibling Gradle projects like ordinary external libraries.
For example, with:
implementation(project(":subproject"))
the old JDT-LS logic emitted the sibling project artifact as:
ScalaGradleSupport then added that JAR as a raw JDT library classpath entry. After Java: Reload Projects, JDT could therefore resolve classes from the generated JAR instead of the workspace project/source. Cleaning the Java LS workspace temporarily removed that polluted classpath state, which explains why cleaning appeared to fix the problem.
This was fixed upstream in eclipse-jdtls/eclipse.jdt.ls#3815 ("Fix Scala Gradle classpath pollution"), commit 7dcd820. The fix:
only runs the Scala classpath augmentation for actual Scala projects;
excludes ProjectComponentIdentifier artifacts, so inter-project Gradle dependencies remain project dependencies instead of build/libs/*.jar entries.
I reproduced the issue with the JDT-LS 1.59 snapshot bundled by redhat.java 1.55.0, then tested the newer redhat.java 1.56.202608**2811** prerelease, which bundles JDT-LS 1.61.0-SNAPSHOT ( git commit f118000). With that version, after:
Java: Clean Java Language Server Workspace
compile the dependent project
Java: Reload Projects
Go to Definition continues to resolve to the sibling project's source (here it is fixed), and the generated project JAR is no longer added as a raw .classpath library entry.
So the practical solution is to upgrade to a redhat.java version containing the JDT-LS #3815 fix; currently it is only the prerelease 1.56.2026071009 build and above that contain the fix.
Thanks for the detailed investigation and confirmation.
PR eclipse-jdtls/eclipse.jdt.ls#3815 fixes the classpath pollution where artifacts from sibling Gradle projects were incorrectly added as raw build/libs/*.jar entries. The test with redhat.java 1.56.2026082811 confirms that it resolves the reload/source-navigation scenario described in the recent comments.
Since the fix is currently available only in a pre-release build, I suggest keeping this issue open until a stable redhat.java release containing the fix is published.
After that release, it would be helpful for @michael-abdul to retest the original cross-directory includeBuild scenario, as the reported Gradle snapshot checksum errors may be a separate issue.
Activity
[-]Java: Clean Java Language Server Workspace[/-][+]Gradle multi-module project breaks on reload, requires cleaning Java Language Server workspace every time[/+]snjeza commentedon Mar 26, 2026
@michael-abdul Could you, please, try the following:
to settings.json
and attach
michael-abdul commentedon Apr 6, 2026
Hi @snjeza, thank you for the suggestions. I followed all the steps you mentioned, but the issue persists. Here is a summary of what I did and what I found:
Steps taken:
.vscode/settings.json:What I found in the logs:
The server log consistently shows these errors on every reload:
However, I confirmed that none of my project's
gradle-wrapper.propertiesfiles reference any snapshot distributions — all usegradle-9.1.0-bin.zip. I verified this with:The result was empty. So these snapshot URLs appear to originate from JDT LS itself, not from my project.
Additionally, I am getting
The import ***** cannot be resolvedin the IDE, even though the cross-module dependency works fine at build time (./gradlew buildsucceeds). I migrated fromproject(':*****')withprojectDirto Composite Build (includeBuild) withdependencySubstitution, but JDT LS still does not resolve the cross-directory module correctly.Environment:
Is there a known workaround for JDT LS not resolving
includeBuildcomposite builds across different directories? Any guidance would be appreciated.wavyfuncollaps commentedon Aug 17, 2026
Hey, I can reproduce something similar. After hours of narrowing down the problem, I can add some details here.
It looks like a closely related issue. In my case the problem specifically affects source navigation after Java: Reload Projects.
Environment
1.55.0, also reproduced with pre-release:1.56.2026081508dependencies { implementation(project(":subproject")) }Both
subprojectandrootprojectare correctly shown as separate projects under JAVA PROJECTS, andJava: List All Java Source Pathscorrectly listssubproject/src/main/java.Reproducer
Starting from a working workspace:
After this, Go to Definition correctly navigates to:
Then:
Source navigation is still correct at this point.
Then execute:
After the reload, Go to Definition no longer navigates to the Java source.
Instead, VS Code opens a decompiled
Main.classusing FernFlower.The source shown by VS Code looks similar to:
Running:
makes source navigation work correctly again.
So the reproducible sequence is:
JDT LS log
With:
the JDT LS log shows that it is treating the Gradle output directory as an external class location.
For example:
and the Eclipse resource is represented through:
During
Java: Reload Projects, JDT LS then updates the classpaths for the complete multi-project build, including:This appears to be the point where the existing Gradle project dependency/source relationship gets replaced or shadowed by the binary output directory:
Afterward, JDT resolves
Mainas a class file rather than:Additional observations
There is no duplicate
Mainsource or class in another project:returns only:
The Gradle dependency is also a real project dependency, not a published JAR:
implementation(project(":subproject"))and
./gradlew ...:dependenciesreports:Deleting
subproject/build/libs/subproject-1.0.jardoes not fix the issue, so this does not appear to be caused by the generated JAR.The important trigger seems to be the classpath refresh performed by Java: Reload Projects when
build/classes/java/mainexists.The issue reproduces with both vscode-java
1.55.0stable and1.56.2026081508pre-release.I can attach the complete JDT Language Server log if that would help.
jhulance commentedon Aug 26, 2026
Can anybody remember when this last worked properly? I wonder if we can narrow down an extension version to revert back to, assuming it's actually an extension issue...
wavyfuncollaps commentedon Aug 28, 2026
I analyzed for hours (learnt a lot) to find the reason:
1.50.0 the problem can be reproduced based on the sequence
1.55.0 the problem can be reproduced based on the sequence
SOLUTION -> 1.56.2026082811 works now!
TL;DR:
The problem occurs only, if I open the source of a class that is inside the subproject. If "Go to Definition" inside the root project, the navigation works.
If I delete the exact class in the "build/classes/com/.../Main.class" inside the subproject, the "Go to Definition" works immediately (maybe it does a refresh in the background because of the filesystem trigger). If I "Reload Projects" it does create a "build" directory again, but with no classes. If i "Clean java Server Workspace" now, "Go to Definition" works and "build" directory still empty. If I call ./gradlew :subproject:compileJava the classes are created as expected. "Go to Definition" works. If I "Reload Projects" -> "Go to Definition" not working anymore. "Java: List all Java source paths" shows all paths to the subprojects source files. These are correct.
I investigated this further for hours using "Extension Dev Host" and found a concrete root cause that matches this behavior:
The problem is in the older JDT-LS Scala/Gradle classpath handling. During a Gradle project reload,
javals.gradletreated artifacts produced by sibling Gradle projects like ordinary external libraries.For example, with:
implementation(project(":subproject"))the old JDT-LS logic emitted the sibling project artifact as:
ScalaGradleSupportthen added that JAR as a raw JDT library classpath entry. AfterJava: Reload Projects, JDT could therefore resolve classes from the generated JAR instead of the workspace project/source. Cleaning the Java LS workspace temporarily removed that polluted classpath state, which explains why cleaning appeared to fix the problem.This was fixed upstream in
eclipse-jdtls/eclipse.jdt.ls#3815("Fix Scala Gradle classpath pollution"), commit7dcd820. The fix:ProjectComponentIdentifierartifacts, so inter-project Gradle dependencies remain project dependencies instead ofbuild/libs/*.jarentries.I reproduced the issue with the JDT-LS 1.59 snapshot bundled by
redhat.java 1.55.0, then tested the newerredhat.java 1.56.202608**2811**prerelease, which bundles JDT-LS1.61.0-SNAPSHOT( git commit f118000). With that version, after:Java: Clean Java Language Server WorkspaceJava: Reload ProjectsGo to Definition continues to resolve to the sibling project's source (here it is fixed), and the generated project JAR is no longer added as a raw
.classpathlibrary entry.So the practical solution is to upgrade to a
redhat.javaversion containing the JDT-LS #3815 fix; currently it is only the prerelease1.56.2026071009build and above that contain the fix.wenytang-ms commentedon Aug 31, 2026
Thanks for the detailed investigation and confirmation.
PR eclipse-jdtls/eclipse.jdt.ls#3815 fixes the classpath pollution where artifacts from sibling Gradle projects were incorrectly added as raw
build/libs/*.jarentries. The test withredhat.java 1.56.2026082811confirms that it resolves the reload/source-navigation scenario described in the recent comments.Since the fix is currently available only in a pre-release build, I suggest keeping this issue open until a stable
redhat.javarelease containing the fix is published.After that release, it would be helpful for @michael-abdul to retest the original cross-directory
includeBuildscenario, as the reported Gradle snapshot checksum errors may be a separate issue.