oraios/serena · error · SolidLSPException

Provided jdtls_path '{jdtls_path}' is not an existing direct

Error message

Provided jdtls_path '{jdtls_path}' is not an existing directory.
Fix: extract jdt-language-server-*.tar.gz from https://download.eclipse.org/jdtls/snapshots/ or run 'brew install jdtls', then set ls_specific_settings.java.jdtls_path to the extracted directory.

What it means

This SolidLSPException is raised in _setup_from_existing_install when the configured jdtls_path does not exist as a directory on disk. Upstream JDTLS mode expects the user to have extracted the official jdt-language-server tarball (or installed via brew) and pointed jdtls_path at the extracted root.

Source

Thrown at src/solidlsp/language_servers/eclipse_jdtls.py:475

            )

        @staticmethod
        def _setup_from_existing_install(
            jdtls_path: str, lombok_path: str, custom_settings: SolidLSPSettings.CustomLSSettings
        ) -> RuntimeDependencyPaths:
            """
            Builds RuntimeDependencyPaths from an already-installed upstream JDTLS distribution
            and the system-installed JDK. No downloads are performed.

            :param jdtls_path: absolute path to the JDTLS root (containing ``plugins/`` and ``config_<platform>/``)
            :param lombok_path: absolute path to the Lombok jar (mandatory; agent is always attached)
            :param custom_settings: language-server-specific settings from ls_specific_settings.java
            :return: populated RuntimeDependencyPaths with ``gradle_path`` set to ``None``
            """
            # validate jdtls_path structure (root + plugins dir)
            jdtls_root = Path(jdtls_path)
            if not jdtls_root.is_dir():
                raise SolidLSPException(
                    f"Provided jdtls_path '{jdtls_path}' is not an existing directory.\n"
                    f"Fix: extract jdt-language-server-*.tar.gz from "
                    f"https://download.eclipse.org/jdtls/snapshots/ or run 'brew install jdtls', "
                    f"then set ls_specific_settings.java.jdtls_path to the extracted directory."
                )
            plugins_dir = jdtls_root / "plugins"
            if not plugins_dir.is_dir():
                raise SolidLSPException(
                    f"Invalid jdtls_path '{jdtls_path}': 'plugins/' directory not found.\n"
                    f"Expected upstream JDTLS layout (plugins/, config_<platform>/, features/) at the root. "
                    f"If you pointed at a vscode-java extension, use '<extension>/server' instead."
                )

            # resolve the main equinox launcher jar (excluding platform-specific native fragments)
            launcher_jar = EclipseJDTLS.DependencyProvider._resolve_launcher_jar(plugins_dir)

            # resolve the platform-specific config directory under jdtls_root
            config_dir = EclipseJDTLS.DependencyProvider._resolve_config_dir(jdtls_root)

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Extract jdt-language-server-*.tar.gz from https://download.eclipse.org/jdtls/snapshots/ and set jdtls_path to the extracted directory.
  2. Or run 'brew install jdtls' (macOS) and point jdtls_path at the installation prefix directory.
  3. Verify the path with 'ls <jdtls_path>' from the same environment/user running Serena.
  4. Use an absolute path to avoid working-directory ambiguity.
  5. Confirm plugins/, config_<platform>/, features/ exist directly under jdtls_path.

Example fix

// before
"jdtls_path": "/opt/jdt-language-server-latest.tar.gz"
// after
mkdir -p /opt/jdtls && tar -xzf jdt-language-server-latest.tar.gz -C /opt/jdtls
"jdtls_path": "/opt/jdtls"
Defensive patterns

Strategy: validation

Validate before calling

import os
p = os.path.expanduser(settings['ls_specific_settings']['java']['jdtls_path'])
assert os.path.isdir(p), f"jdtls_path '{p}' is not a directory — extract the JDTLS tarball first"

Type guard

def is_valid_jdtls_root(path: str) -> bool:
    from pathlib import Path
    root = Path(path).expanduser()
    return root.is_dir() and (root / 'plugins').is_dir() and any(root.glob('config_*'))

Try / catch

try:
    ls = SolidLSP(java_config)
except SolidLSPException as e:
    if 'not an existing directory' in str(e):
        raise SystemExit(f"Fix jdtls_path: {e}")
    raise

Prevention

When it happens

Trigger: Starting EclipseJDTLS in upstream mode where Path(jdtls_path).is_dir() is False: path never existed, tarball was never extracted, wrong directory given, or relative path resolved differently than expected.

Common situations: User set jdtls_path to the .tar.gz file itself instead of the extracted folder; typed a path with a typo; used a path valid inside a container but not on the host; deleted the directory after configuring.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/ebdd2c02b2aa760a. Report an issue: GitHub.