{"record":{"id":"3efb258a71a6b61b","repo":"oraios/serena","slug":"java-home-explicit-home-is-invalid-candidat","errorCode":null,"errorMessage":"java_home='{explicit_home}' is invalid: '{candidate}' does not exist. Set ls_specific_settings.java.java_home to a JDK home that contains bin/{java_exe_name}.","messagePattern":"java_home='(.+?)' is invalid: '(.+?)' does not exist\\. Set ls_specific_settings\\.java\\.java_home to a JDK home that contains bin/(.+?)\\.","errorType":"exception","errorClass":"SolidLSPException","httpStatus":null,"severity":"error","filePath":"src/solidlsp/language_servers/eclipse_jdtls.py","lineNumber":588,"sourceCode":"            The ``java`` executable is located by priority: ``java_home`` setting ->\n            ``JAVA_HOME`` env var -> ``java`` in PATH. The actual JDK home directory and\n            major version are then discovered by querying the JVM itself via\n            ``java -XshowSettings:properties -version`` — this is the single source of truth\n            and works correctly even when the locator is a system stub (e.g. ``/usr/bin/java``\n            on macOS, which delegates to ``/usr/libexec/java_home`` under the hood and does not\n            resolve to the real JDK home via simple path traversal).\n\n            :return: (jdk_home_directory, java_executable_path)\n            \"\"\"\n            # locate a java executable to interrogate\n            java_exe_name = \"java.exe\" if platform.system() == \"Windows\" else \"java\"\n            java_exe: str | None = None\n            source: str\n\n            if explicit_home := custom_settings.get(\"java_home\"):\n                candidate = str(Path(explicit_home) / \"bin\" / java_exe_name)\n                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. \"","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/solidlsp/language_servers/eclipse_jdtls.py#L570-L606","documentation":"SolidLSPException thrown by _resolve_system_jdk when the explicit ls_specific_settings.java.java_home setting points to a directory that does not contain bin/<java executable>. The library validates the candidate JDK before using it so JDTLS never starts with a broken java path.","triggerScenarios":"Setting ls_specific_settings.java.java_home to a path where Path(home)/bin/java does not exist; _setup_from_existing_install calls _resolve_system_jdk which checks os.path.exists(candidate) and raises immediately.","commonSituations":"Typo in java_home path; pointing java_home at the JDK's parent directory instead of the JDK home; pointing at a JRE-less runtime image without bin/java; path changed after a JDK upgrade; Windows users giving the java.exe file path instead of the home directory.","solutions":["Set ls_specific_settings.java.java_home to a real JDK home that contains bin/java (e.g. /usr/lib/jvm/temurin-21-jdk-amd64)","Verify with: ls <java_home>/bin/java (or bin/java.exe on Windows)","Remove the java_home setting to fall back to JAVA_HOME or PATH","Update the path if the JDK was upgraded/moved"],"exampleFix":"// before\nls_specific_settings:\n  java:\n    java_home: /usr/lib/jvm/java-21  # does not exist\n// after\nls_specific_settings:\n  java:\n    java_home: /usr/lib/jvm/temurin-21-jdk-amd64  # contains bin/java","handlingStrategy":"validation","validationCode":"from pathlib import Path\nimport os\ndef validate_java_home(java_home: str, exe: str = \"java\") -> bool:\n    return os.path.exists(Path(java_home) / \"bin\" / exe)","typeGuard":"def is_valid_jdk_home(p: object) -> bool:\n    return isinstance(p, (str, Path)) and (Path(p) / \"bin\" / (\"java.exe\" if os.name == \"nt\" else \"java\")).exists()","tryCatchPattern":"try:\n    ls = start_jdtls(settings)\nexcept SolidLSPException as e:\n    if str(e).startswith(\"java_home=\"):\n        settings.pop(\"java_home\", None)  # fall back to JAVA_HOME/PATH and retry\n        ls = start_jdtls(settings)\n    else:\n        raise","preventionTips":["Always point java_home at the JDK root (the dir containing bin/), not a parent or the binary itself","Add a startup check that <java_home>/bin/java exists before launching","Update the setting as part of your JDK upgrade runbook","On Windows use the home dir and let the library resolve java.exe"],"tags":["java","jdk","configuration","path-validation"],"backgroundTag":"invalid-java-home-path","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}