oraios/serena · error · SolidLSPException

Both 'jdtls_path' and 'lombok_path' must be set together in

Error message

Both 'jdtls_path' and 'lombok_path' must be set together in ls_specific_settings.java to use the upstream JDTLS mode. Set both, or remove both to use the default vscode-java VSIX mode.

What it means

This SolidLSPException is raised during EclipseJDTLS setup when ls_specific_settings.java contains exactly one of 'jdtls_path' or 'lombok_path'. Upstream JDTLS mode requires both paths together (the server needs the lombok jar on its javaagent line), so a partial configuration is rejected with guidance to set both or neither.

Source

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

            """
            Setup runtime dependencies for EclipseJDTLS and return the paths.

            Two modes are supported:

            * **Upstream JDTLS mode** (activated when both ``jdtls_path`` and ``lombok_path`` are set
              in ``ls_specific_settings.java``): uses an existing JDTLS installation (e.g. via
              ``brew install jdtls`` or extracted ``jdt-language-server-*.tar.gz``) and the system JDK.
              Nothing is downloaded by Serena. Suitable for restricted-network/corporate environments.
            * **Default vscode-java VSIX mode** (activated otherwise): downloads the platform-specific
              vscode-java VSIX bundle (containing JDTLS, bundled JRE 21 and Lombok) and a Gradle
              distribution from public hosts.
            """
            jdtls_path = custom_settings.get("jdtls_path")
            lombok_path = custom_settings.get("lombok_path")
            if jdtls_path or lombok_path:
                # both must be set together to activate upstream mode
                if not (jdtls_path and lombok_path):
                    raise SolidLSPException(
                        "Both 'jdtls_path' and 'lombok_path' must be set together in "
                        "ls_specific_settings.java to use the upstream JDTLS mode. "
                        "Set both, or remove both to use the default vscode-java VSIX mode."
                    )
                return EclipseJDTLS.DependencyProvider._setup_from_existing_install(str(jdtls_path), str(lombok_path), custom_settings)

            platformId = PlatformUtils.get_platform_id()
            gradle_version = custom_settings.get("gradle_version", cls.DEFAULT_GRADLE_VERSION)
            vscode_java_version = custom_settings.get("vscode_java_version", cls.DEFAULT_VSCODE_JAVA_VERSION)

            # install-dir name per the version-pinning convention (see module-level block):
            # INITIAL -> legacy unversioned dir; everything else -> "{name}-{resolved}" subdir
            vscode_java_dirname = (
                "vscode-java" if vscode_java_version == cls.INITIAL_VSCODE_JAVA_VERSION else f"vscode-java-{vscode_java_version}"
            )

            # Resolve internal VSIX paths (JRE / Lombok / launcher filenames). For pinned versions
            # these are known; for any other user-supplied version we bail out — guessing would

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Set BOTH 'jdtls_path' and 'lombok_path' in ls_specific_settings.java to enable upstream JDTLS mode.
  2. Alternatively remove both keys to fall back to the default vscode-java VSIX mode.
  3. Check for typos in the settings keys and ensure both entries are under ls_specific_settings.java.
  4. Restart the session after correcting the configuration.

Example fix

// before (invalid: only one key)
{"ls_specific_settings": {"java": {"jdtls_path": "/opt/jdtls"}}}
// after
{"ls_specific_settings": {"java": {"jdtls_path": "/opt/jdtls", "lombok_path": "~/.m2/repository/org/projectlombok/lombok/1.18.34/lombok-1.18.34.jar"}}}
Defensive patterns

Strategy: validation

Validate before calling

import os
java = settings.get('ls_specific_settings', {}).get('java', {})
keys = ('jdtls_path', 'lombok_path')
present = [k for k in keys if java.get(k)]
if len(present) == 1:
    raise ValueError(f"{present[0]} set but not the other; set both or neither")

Type guard

def upstream_jdtls_config_complete(java_settings: dict) -> bool:
    return bool(java_settings.get('jdtls_path')) == bool(java_settings.get('lombok_path')) and (
        not java_settings.get('jdtls_path') or (
            os.path.isdir(os.path.expanduser(java_settings['jdtls_path'])) and
            os.path.isfile(os.path.expanduser(java_settings['lombok_path']))
        )
    )

Try / catch

try:
    ls = SolidLSP(java_config)
except SolidLSPException as e:
    if "must be set together" in str(e):
        java_config['ls_specific_settings']['java'].pop('jdtls_path', None)
        java_config['ls_specific_settings']['java'].pop('lombok_path', None)
        ls = SolidLSP(java_config)  # fall back to VSIX mode
    else:
        raise

Prevention

When it happens

Trigger: Creating an EclipseJDTLS language server (via _setup_runtime_dependencies, called from __init__) when custom_settings.get('jdtls_path') XOR custom_settings.get('lombok_path') is truthy under ls_specific_settings.java.

Common situations: User adds jdtls_path but forgets lombok_path (or vice versa); leftover key from a previous config edit; typo'd or renamed key so only one is picked up; example docs showing only one setting.

Related errors


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