Skip to content

JDTLS workspace cache is not invalidated when ls_specific_settings changes, causing silent project import failures #1541

@intfoo

Description

@intfoo

I don't know what the reason is, it's not easily reproducible and we don't have time to dig in here. Maybe it was a space issue, which would then be resolved by #1245. Could you try again @CNAHYZ ?

Originally posted by @MischaPanch in #1174

Symbol search fails on Java project with LSP backend #1174

I've found the reason: my Maven repository and configuration files aren't in the default ~/.m2 path. I added the path to configure it project.local.yml fine, but I think Serena should address this issue (including the workspace issue below) with some humane solutions (adding logs, giving prompts, etc.), otherwise users will have trouble finding the problem and eventually abandon the tool

Summary

When ls_specific_settings.java in the project configuration (project.local.yml / serena_config.yml) is modified — for example, changing maven_user_settings or gradle_user_home — the JDTLS workspace cache is not invalidated. This leads to two distinct failure modes:

  1. Silent success on cached workspaces: After a successful import with correct Maven settings, removing or changing maven_user_settings still appears to work because JDTLS reuses the cached project index. This masks configuration errors until the cache is manually cleared.
  2. Silent failure on fresh imports: When the workspace cache is cleared (or on first run) and maven_user_settings points to a non-default location (e.g., D:\programs\apache-maven-3.6.3\conf\settings.xml instead of ~/.m2/settings.xml), JDTLS cannot resolve parent POMs and returns empty symbol lists without any user-visible error. The health check fails with No symbols found, which gives no indication that the real problem is Maven configuration.

Environment

  • OS: Windows 11
  • Serena version: latest (via uv tool install)
  • JDTLS version: 1.58.0-SNAPSHOT (vscode-java VSIX mode)
  • Project type: Maven multi-module (23 modules) with a private parent POM (com.xxx:xxx-parent:4.0.0-rds-SNAPSHOT) not available in ~/.m2/repository
  • Maven configuration: Custom settings.xml at D:\programs\apache-maven-3.6.3\conf\settings.xml, local repository at D:\repository\

Reproduction

Setup

  1. Have a Maven project whose pom.xml references a parent POM not in ~/.m2/repository but available in a custom local repository defined in a non-default settings.xml.

  2. Configure project.local.yml:

    ls_specific_settings:
      java:
        maven_user_settings: "D:\\programs\\apache-maven-3.6.3\\conf\\settings.xml"
  3. Run serena project health-checkpasses (workspace is imported with correct Maven settings).

  4. Comment out or remove the maven_user_settings line.

  5. Run serena project health-check again — still passes because the JDTLS workspace cache is reused.

Fresh failure

  1. Delete the workspace cache: rm -rf ~/.serena/language_servers/static/EclipseJDTLS/workspaces/<hash>

  2. Run serena project health-checkfails with No symbols found in file ....

  3. The JDTLS workspace .markers file shows:

    Non-resolvable parent POM for com.adups:iov-config-core:2.0.0: 
    Could not find artifact com.xxx:xxx-parent:pom:4.0.0-rds-SNAPSHOT 
    and 'parent.relativePath' points at wrong local POM
    

The user sees "No symbols found" but has no way to know this is a Maven configuration issue.

Root Cause Analysis

The JDTLS workspace directory hash is computed in eclipse_jdtls.py (_compute_workspace_hash):

def _compute_workspace_hash(repository_root_path, jdtls_launcher_jar_path, custom_settings):
    is_legacy_initial = (...)
    if is_legacy_initial:
        ws_hash_input = repository_root_path.encode()
    else:
        ws_hash_input = (repository_root_path + "|" + jdtls_launcher_jar_path).encode()
    return hashlib.md5(ws_hash_input).hexdigest()

The hash input is repository_root_path + jdtls_launcher_jar_path. It does not include:

  • maven_user_settings
  • gradle_user_home
  • java_home
  • Any other ls_specific_settings values

Therefore, changing any of these settings does not trigger a new workspace import. JDTLS silently reuses the old (stale) project index, or — on first import — fails without a clear error message.

Proposed Solutions

Option A: Auto-invalidate workspace on config change (recommended)

Include the relevant ls_specific_settings values in the workspace hash calculation:

def _compute_workspace_hash(repository_root_path, jdtls_launcher_jar_path, custom_settings):
    config_keys = [
        "maven_user_settings",
        "gradle_user_home",
        "gradle_wrapper_enabled",
        "maven_offline",
    ]
    config_hash_input = "|".join(str(custom_settings.get(k, "")) for k in config_keys)
    ws_hash_input = (repository_root_path + "|" + jdtls_launcher_jar_path + "|" + config_hash_input).encode()
    return hashlib.md5(ws_hash_input).hexdigest()

This ensures any relevant configuration change triggers a fresh workspace import. The trade-off is that users may see a reimport on every config tweak, but this is preferable to silent failures.

Option B: CLI command to clear workspace cache

Add a serena project clear-cache (or serena project reset-language-server) command that:

  1. Deletes the JDTLS workspace directory for the current project
  2. Clears the symbol cache (document_symbols.pkl, raw_document_symbols.pkl)
  3. Optionally re-triggers a health check
serena project clear-cache [--language java]

This gives users explicit control when they know they've changed configuration.

Option C: Surface Maven import errors to the user

When JDTLS returns 0 symbols for a file during health check, check the workspace .markers files for build errors and include them in the error message. Currently the failure chain is:

Maven POM resolution fails → JDTLS build fails → textDocument/documentSymbol returns [] → "No symbols found"

The user only sees the final symptom. Intercepting and surfacing the root cause would significantly improve debuggability.

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