{"record":{"id":"4ad21be4ee6252f7","repo":"oraios/serena","slug":"could-not-locate-a-java-installation-for-jdtls-se","errorCode":null,"errorMessage":"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}+.","messagePattern":"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 (.+?)\\+\\.","errorType":"exception","errorClass":"SolidLSPException","httpStatus":null,"severity":"error","filePath":"src/solidlsp/language_servers/eclipse_jdtls.py","lineNumber":605,"sourceCode":"                if not os.path.exists(candidate):\n                    raise SolidLSPException(\n                        f\"java_home='{explicit_home}' is invalid: '{candidate}' does not exist. \"\n                        f\"Set ls_specific_settings.java.java_home to a JDK home that contains bin/{java_exe_name}.\"\n                    )\n                java_exe = candidate\n                source = f\"java_home setting ({explicit_home})\"\n            elif env_home := os.environ.get(\"JAVA_HOME\"):\n                candidate = str(Path(env_home) / \"bin\" / java_exe_name)\n                if os.path.exists(candidate):\n                    java_exe = candidate\n                    source = f\"JAVA_HOME env ({env_home})\"\n                else:\n                    log.warning(f\"JAVA_HOME='{env_home}' invalid (no '{candidate}'), falling back to PATH.\")\n\n            if java_exe is None:\n                java_in_path = shutil.which(\"java\")\n                if java_in_path is None:\n                    raise SolidLSPException(\n                        \"Could not locate a Java installation for JDTLS. \"\n                        \"Set ls_specific_settings.java.java_home, set JAVA_HOME environment variable, \"\n                        f\"or ensure 'java' is on PATH. Required: JDK {JDTLS_MIN_JDK_VERSION}+.\"\n                    )\n                java_exe = java_in_path\n                source = f\"PATH ({java_in_path})\"\n\n            # interrogate the JVM for its real java.home and version (single source of truth)\n            real_jdk_home, major_version = EclipseJDTLS.DependencyProvider._inspect_java(java_exe)\n\n            # validate version\n            if major_version < JDTLS_MIN_JDK_VERSION:\n                raise SolidLSPException(\n                    f\"JDTLS requires JDK {JDTLS_MIN_JDK_VERSION}+ but '{java_exe}' is JDK {major_version} \"\n                    f\"(located via {source}, java.home={real_jdk_home}). \"\n                    f\"Install a newer JDK and update ls_specific_settings.java.java_home or JAVA_HOME.\"\n                )\n            log.info(f\"Resolved JDK {major_version} via {source}; java.home={real_jdk_home}; java_exe={java_exe}.\")","sourceCodeStart":587,"sourceCodeEnd":623,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/solidlsp/language_servers/eclipse_jdtls.py#L587-L623","documentation":"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.","triggerScenarios":"_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.","commonSituations":"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.","solutions":["Install a JDK 17+ (JDTLS_MIN_JDK_VERSION) and ensure 'java' is on PATH","Set the JAVA_HOME environment variable to the JDK home","Set ls_specific_settings.java.java_home in the config to an explicit JDK home","Verify with: which java && java -version"],"exampleFix":"// before (Dockerfile)\nFROM python:3.12-slim\n// after\nFROM python:3.12-slim\nRUN apt-get update && apt-get install -y openjdk-21-jdk-headless\nENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64","handlingStrategy":"fallback","validationCode":"import shutil, os\nfrom pathlib import Path\ndef java_available() -> bool:\n    if shutil.which(\"java\"):\n        return True\n    home = os.environ.get(\"JAVA_HOME\")\n    return bool(home and (Path(home) / \"bin\" / \"java\").exists())","typeGuard":"def has_discoverable_java(env: dict) -> bool:\n    return bool(env.get(\"JAVA_HOME\")) or shutil.which(\"java\") is not None","tryCatchPattern":"try:\n    ls = start_jdtls()\nexcept SolidLSPException as e:\n    if \"Could not locate a Java installation\" in str(e):\n        install_jdk(21)  # or set JAVA_HOME / java_home setting\n        ls = start_jdtls()\n    else:\n        raise","preventionTips":["Bake a JDK into Docker images used to run the service","Set JAVA_HOME explicitly in deployment/CI environments with sanitized env","Verify 'java -version' works in the target environment before enabling JDTLS","Prefer the explicit java_home setting in containers where PATH is minimal"],"tags":["java","jdk","environment","path-resolution"],"backgroundTag":"java-not-found","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}