oraios/serena · error · SolidLSPException

Could not locate a Java installation for JDTLS. Set ls_speci

Error message

Could not locate a Java installation for JDTLS. Set ls_specific_settings.java.java_home, set JAVA_HOME environment variable, or ensure 'java' is on PATH. Required: JDK {JDTLS_MIN_JDK_VERSION}+.

What it means

SolidLSPException thrown by _resolve_system_jdk after exhausting all discovery strategies (explicit java_home setting, JAVA_HOME env var, and 'java' on PATH) without finding a usable Java executable. JDTLS cannot run without a JDK, so startup aborts with actionable instructions.

Source

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

                if not os.path.exists(candidate):
                    raise SolidLSPException(
                        f"java_home='{explicit_home}' is invalid: '{candidate}' does not exist. "
                        f"Set ls_specific_settings.java.java_home to a JDK home that contains bin/{java_exe_name}."
                    )
                java_exe = candidate
                source = f"java_home setting ({explicit_home})"
            elif env_home := os.environ.get("JAVA_HOME"):
                candidate = str(Path(env_home) / "bin" / java_exe_name)
                if os.path.exists(candidate):
                    java_exe = candidate
                    source = f"JAVA_HOME env ({env_home})"
                else:
                    log.warning(f"JAVA_HOME='{env_home}' invalid (no '{candidate}'), falling back to PATH.")

            if java_exe is None:
                java_in_path = shutil.which("java")
                if java_in_path is None:
                    raise SolidLSPException(
                        "Could not locate a Java installation for JDTLS. "
                        "Set ls_specific_settings.java.java_home, set JAVA_HOME environment variable, "
                        f"or ensure 'java' is on PATH. Required: JDK {JDTLS_MIN_JDK_VERSION}+."
                    )
                java_exe = java_in_path
                source = f"PATH ({java_in_path})"

            # interrogate the JVM for its real java.home and version (single source of truth)
            real_jdk_home, major_version = EclipseJDTLS.DependencyProvider._inspect_java(java_exe)

            # validate version
            if major_version < JDTLS_MIN_JDK_VERSION:
                raise SolidLSPException(
                    f"JDTLS requires JDK {JDTLS_MIN_JDK_VERSION}+ but '{java_exe}' is JDK {major_version} "
                    f"(located via {source}, java.home={real_jdk_home}). "
                    f"Install a newer JDK and update ls_specific_settings.java.java_home or JAVA_HOME."
                )
            log.info(f"Resolved JDK {major_version} via {source}; java.home={real_jdk_home}; java_exe={java_exe}.")

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Install a JDK 17+ (JDTLS_MIN_JDK_VERSION) and ensure 'java' is on PATH
  2. Set the JAVA_HOME environment variable to the JDK home
  3. Set ls_specific_settings.java.java_home in the config to an explicit JDK home
  4. Verify with: which java && java -version

Example fix

// before (Dockerfile)
FROM python:3.12-slim
// after
FROM python:3.12-slim
RUN apt-get update && apt-get install -y openjdk-21-jdk-headless
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64
Defensive patterns

Strategy: fallback

Validate before calling

import shutil, os
from pathlib import Path
def java_available() -> bool:
    if shutil.which("java"):
        return True
    home = os.environ.get("JAVA_HOME")
    return bool(home and (Path(home) / "bin" / "java").exists())

Type guard

def has_discoverable_java(env: dict) -> bool:
    return bool(env.get("JAVA_HOME")) or shutil.which("java") is not None

Try / catch

try:
    ls = start_jdtls()
except SolidLSPException as e:
    if "Could not locate a Java installation" in str(e):
        install_jdk(21)  # or set JAVA_HOME / java_home setting
        ls = start_jdtls()
    else:
        raise

Prevention

When it happens

Trigger: _setup_from_existing_install -> _resolve_system_jdk where: no java_home in custom settings, JAVA_HOME unset (or set but invalid, logged as warning and skipped), and shutil.which('java') returns None.

Common situations: Fresh Docker image / CI runner with no JDK installed; Java not on PATH in the service environment; JAVA_HOME pointing at a deleted directory; running under systemd or an IDE with a sanitized environment.

Related errors


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