oraios/serena · error · SolidLSPException

No main Equinox launcher jar found in '{plugins_dir}'. Expec

Error message

No main Equinox launcher jar found in '{plugins_dir}'. Expected file like 'org.eclipse.equinox.launcher_<version>.jar'. Verify the JDTLS extraction is complete and not corrupted.

What it means

This SolidLSPException is raised when no main Equinox OSGi launcher jar (org.eclipse.equinox.launcher_<version>.jar) can be found in the JDTLS plugins directory. The launcher jar is the entrypoint JDTLS is started with; its absence means the extraction is incomplete or corrupted. Native launcher fragments (with extra dotted segments after the underscore) are deliberately excluded by the regex.

Source

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

                jdtls_readonly_config_path=str(config_dir),
                lombok_jar_path=lombok_path,
                gradle_path=None,
            )

        @staticmethod
        def _resolve_launcher_jar(plugins_dir: Path) -> Path:
            """
            Locates the main Equinox launcher jar in JDTLS's ``plugins/`` directory, excluding
            platform-specific native fragments like ``org.eclipse.equinox.launcher.cocoa.macosx.*``.

            :return: path to the main launcher jar (e.g. ``org.eclipse.equinox.launcher_1.7.0.v....jar``)
            """
            # main launcher matches: org.eclipse.equinox.launcher_<digit>...jar (single underscore,
            # immediately followed by version digits — fragments have additional dotted segments).
            pattern = re.compile(r"^org\.eclipse\.equinox\.launcher_\d.*\.jar$")
            matches = sorted(p for p in plugins_dir.glob("org.eclipse.equinox.launcher_*.jar") if pattern.match(p.name))
            if not matches:
                raise SolidLSPException(
                    f"No main Equinox launcher jar found in '{plugins_dir}'. "
                    f"Expected file like 'org.eclipse.equinox.launcher_<version>.jar'. "
                    f"Verify the JDTLS extraction is complete and not corrupted."
                )
            # if multiple versions are present (rare), pick the highest by name
            return matches[-1]

        @staticmethod
        def _resolve_config_dir(jdtls_root: Path) -> Path:
            """
            Locates the platform-specific OSGi configuration directory inside the JDTLS root.

            :return: path to ``config_<platform>/`` directory matching the current OS/arch
            """
            platform_id = PlatformUtils.get_platform_id().value
            config_dir_name = JDTLS_CONFIG_DIR_BY_PLATFORM.get(platform_id)
            if config_dir_name is None:
                raise SolidLSPException(

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Re-extract the official jdt-language-server tarball to restore the full plugins/ directory.
  2. Confirm with 'ls plugins/ | grep equinox.launcher' that a jar like org.eclipse.equinox.launcher_1.x.x.vYYYY.jar exists.
  3. If a native fragment jar (name with extra dots after underscore) is present but the main jar isn't, the extraction is broken — restore it.
  4. Disable antivirus interference or re-download if files were quarantined.
  5. Fall back to default vscode-java VSIX mode by removing jdtls_path/lombok_path.

Example fix

# before: plugins/ missing launcher
$ ls /opt/jdtls/plugins | grep launcher
org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.2.900.jar
# after: re-extract
tar -xzf jdt-language-server-latest.tar.gz -C /opt/jdtls
$ ls /opt/jdtls/plugins | grep '^org.eclipse.equinox.launcher_'
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
plugins = Path(jdtls_path).expanduser() / 'plugins'
launchers = [p for p in plugins.glob('org.eclipse.equinox.launcher_*.jar')
             if not p.name.split('_')[1].split('.')[0].isdigit() or p.name.count('.') >= 0]
# simple pre-check: at least one non-fragment launcher
assert any(p.name.startswith('org.eclipse.equinox.launcher_') and p.name[len('org.eclipse.equinox.launcher_'):].split('.')[0].isdigit()
           for p in plugins.glob('org.eclipse.equinox.launcher_*.jar')), 'main launcher jar missing'

Type guard

def has_main_launcher_jar(jdtls_root) -> bool:
    import re
    from pathlib import Path
    pattern = re.compile(r'^org\.eclipse\.equinox\.launcher_\d.*\.jar$')
    plugins = Path(jdtls_root) / 'plugins'
    return plugins.is_dir() and any(pattern.match(p.name) for p in plugins.glob('org.eclipse.equinox.launcher_*.jar'))

Try / catch

try:
    ls = SolidLSP(java_config)
except SolidLSPException as e:
    if 'No main Equinox launcher jar' in str(e):
        reextract_jdtls_tarball(jdtls_path)
        ls = SolidLSP(java_config)
    else:
        raise

Prevention

When it happens

Trigger: _resolve_launcher_jar globs plugins_dir for 'org.eclipse.equinox.launcher_*.jar', filters by the main-launcher regex, and raises when no match survives — during upstream JDTLS setup.

Common situations: Interrupted or partial tarball extraction; antivirus quarantined jars; user manually pruned 'duplicate' launcher jars (removing the real one, keeping only fragments); pointing plugins dir at wrong vscode-java subfolder.

Related errors


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