{"record":{"id":"62a38dc950766b67","repo":"oraios/serena","slug":"invalid-jdtls-path-jdtls-path-plugins-dire","errorCode":null,"errorMessage":"Invalid jdtls_path '{jdtls_path}': 'plugins/' directory not found.\nExpected upstream JDTLS layout (plugins/, config_<platform>/, features/) at the root. If you pointed at a vscode-java extension, use '<extension>/server' instead.","messagePattern":"Invalid jdtls_path '(.+?)': 'plugins/' directory not found\\.\nExpected upstream JDTLS layout \\(plugins/, config_<platform>/, features/\\) at the root\\. If you pointed at a vscode-java extension, use '<extension>/server' instead\\.","errorType":"exception","errorClass":"SolidLSPException","httpStatus":null,"severity":"error","filePath":"src/solidlsp/language_servers/eclipse_jdtls.py","lineNumber":483,"sourceCode":"            and the system-installed JDK. No downloads are performed.\n\n            :param jdtls_path: absolute path to the JDTLS root (containing ``plugins/`` and ``config_<platform>/``)\n            :param lombok_path: absolute path to the Lombok jar (mandatory; agent is always attached)\n            :param custom_settings: language-server-specific settings from ls_specific_settings.java\n            :return: populated RuntimeDependencyPaths with ``gradle_path`` set to ``None``\n            \"\"\"\n            # validate jdtls_path structure (root + plugins dir)\n            jdtls_root = Path(jdtls_path)\n            if not jdtls_root.is_dir():\n                raise SolidLSPException(\n                    f\"Provided jdtls_path '{jdtls_path}' is not an existing directory.\\n\"\n                    f\"Fix: extract jdt-language-server-*.tar.gz from \"\n                    f\"https://download.eclipse.org/jdtls/snapshots/ or run 'brew install jdtls', \"\n                    f\"then set ls_specific_settings.java.jdtls_path to the extracted directory.\"\n                )\n            plugins_dir = jdtls_root / \"plugins\"\n            if not plugins_dir.is_dir():\n                raise SolidLSPException(\n                    f\"Invalid jdtls_path '{jdtls_path}': 'plugins/' directory not found.\\n\"\n                    f\"Expected upstream JDTLS layout (plugins/, config_<platform>/, features/) at the root. \"\n                    f\"If you pointed at a vscode-java extension, use '<extension>/server' instead.\"\n                )\n\n            # resolve the main equinox launcher jar (excluding platform-specific native fragments)\n            launcher_jar = EclipseJDTLS.DependencyProvider._resolve_launcher_jar(plugins_dir)\n\n            # resolve the platform-specific config directory under jdtls_root\n            config_dir = EclipseJDTLS.DependencyProvider._resolve_config_dir(jdtls_root)\n\n            # validate lombok jar exists\n            if not Path(lombok_path).is_file():\n                raise SolidLSPException(\n                    f\"Provided lombok_path '{lombok_path}' does not exist or is not a file.\\n\"\n                    f\"Fix: download lombok jar from https://projectlombok.org/downloads/ or use the one \"\n                    f\"from your local Maven cache (~/.m2/repository/org/projectlombok/lombok/<version>/lombok-<version>.jar).\"\n                )","sourceCodeStart":465,"sourceCodeEnd":501,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/solidlsp/language_servers/eclipse_jdtls.py#L465-L501","documentation":"This SolidLSPException is raised when jdtls_path exists but lacks a 'plugins/' subdirectory, meaning it does not match the upstream JDTLS layout (plugins/, config_<platform>/, features/). A very common cause is pointing jdtls_path at the vscode-java extension root instead of its 'server' subdirectory.","triggerScenarios":"_setup_from_existing_install passes is_dir() for jdtls_root but (jdtls_root / 'plugins').is_dir() is False during EclipseJDTLS startup in upstream mode.","commonSituations":"User set jdtls_path to a vscode-java VSIX extension directory (needs '<extension>/server'); extracted the tarball into a nested folder so the real root is one level deeper; pointed at a brew Cellar parent rather than the libexec directory.","solutions":["If pointing at a vscode-java extension, append '/server' to the path (e.g. '<ext_dir>/server').","Inspect jdtls_path for a nested directory containing plugins/, config_<platform>/, features/ and point at that root.","Re-extract the official JDTLS tarball so the layout sits directly under jdtls_path.","On macOS with brew, use the libexec directory of the jdtls formula as jdtls_path."],"exampleFix":"// before\n\"jdtls_path\": \"/Users/me/.vscode/extensions/redhat.java-1.30.0\"\n// after\n\"jdtls_path\": \"/Users/me/.vscode/extensions/redhat.java-1.30.0/server\"","handlingStrategy":"validation","validationCode":"from pathlib import Path\nroot = Path(jdtls_path).expanduser()\nif root.is_dir() and not (root / 'plugins').is_dir():\n    server = root / 'server'  # vscode-java extension layout\n    if (server / 'plugins').is_dir():\n        settings['ls_specific_settings']['java']['jdtls_path'] = str(server)","typeGuard":"def has_upstream_jdtls_layout(path: str) -> bool:\n    from pathlib import Path\n    root = Path(path).expanduser()\n    return root.is_dir() and (root / 'plugins').is_dir() and (root / 'features').is_dir()","tryCatchPattern":"try:\n    ls = SolidLSP(java_config)\nexcept SolidLSPException as e:\n    if \"'plugins/' directory not found\" in str(e):\n        cfg = java_config['ls_specific_settings']['java']\n        cfg['jdtls_path'] = str(Path(cfg['jdtls_path']) / 'server')\n        ls = SolidLSP(java_config)\n    else:\n        raise","preventionTips":["Check for plugins/, config_<platform>/, features/ at the configured root before saving settings.","For vscode-java extensions, always use the '<extension>/server' subdirectory.","Avoid symlink/nested-extraction surprises: extract tarballs with 'tar -xzf' directly into the target root."],"tags":["java","jdtls","configuration","directory-layout"],"backgroundTag":"invalid-directory-layout","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}