LSP plugin: workspaceFolder defaults to null, breaking JDTLS project detection
Summary
The official jdtls-lsp plugin (and likely other LSP plugins) doesn't set workspaceFolder in its config. Claude Code appears to send a null or empty rootUri in the LSP initialize request, causing JDTLS to fall back to "invisible project" / syntax-only mode. Every other LSP client (VSCode, Neovim, Emacs, etc.) defaults rootUri to the workspace/project root directory.
This makes JDTLS unable to:
- Find
.project/.classpathfiles (Eclipse project detection) - Find
pom.xml/build.gradle(Maven/Gradle project detection) - Index the workspace for cross-file navigation
Steps to Reproduce
- Install
jdtls-lsp@claude-plugins-officialand havejdtlsbinary in PATH - Open a Java project that has a
.projectfile at the root - Use any LSP operation (e.g.,
findReferences,goToDefinition) - Observe: JDTLS log shows
"Creating the Java project jdt.ls-java-project"(the fallback invisible project) instead of importing the actual project - Observe: diagnostics show
"X.java is a non-project file, only syntax errors are reported"
Root Cause
The jdtls-lsp plugin config in the official marketplace only specifies:
{
"jdtls": {
"command": "jdtls",
"extensionToLanguage": { ".java": "java" },
"startupTimeout": 120000
}
}
No workspaceFolder is set. Claude Code does not appear to default it to the current working directory.
JDTLS logs confirm:
"Importers: GradleProjectImporter, MavenProjectImporter, EclipseProjectImporter, InvisibleProjectImporter""Workspace initialized in 22ms"(too fast — nothing was found)- Falls straight through to
InvisibleProjectImporter
Secondary Issue: settings not delivered via workspace/didChangeConfiguration
The LSP plugin schema supports a settings field described as "Settings passed via workspace/didChangeConfiguration". However, even when set in .lsp.json:
{
"jdtls": {
"settings": {
"java.project.sourcePaths": ["src"],
"java.project.referencedLibraries": ["lib/*.jar"]
}
}
}
...JDTLS does not receive these settings. The invisible project's .classpath remains at defaults (path="src") rather than reflecting the configured source paths. This suggests workspace/didChangeConfiguration is never sent.
Workaround
Create a local plugin with workspaceFolder explicitly set, plus Eclipse project files (.project, .classpath) at the workspace root:
{
"jdtls": {
"command": "jdtls",
"extensionToLanguage": { ".java": "java" },
"workspaceFolder": "/absolute/path/to/project",
"startupTimeout": 120000
}
}
Load with claude --plugin-dir ./path/to/local/plugin after disabling the official plugin.
Expected Behavior
- When
workspaceFolderis not set in the plugin config, Claude Code should default it to the current working directory (consistent with all other LSP clients) settingsfrom the plugin config should be delivered to the LSP server viaworkspace/didChangeConfigurationafter initialization
Environment
- Claude Code: latest (2026-03-22)
- JDTLS: 1.57.0-SNAPSHOT (milestone build Feb 2026)
- OS: Linux (Ubuntu)
- Java: OpenJDK 21
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗