oraios/serena · error · RuntimeError

Erlang/OTP not found. Install from: https://www.erlang.org/d

Error message

Erlang/OTP not found. Install from: https://www.erlang.org/downloads

What it means

After confirming erlang_ls exists, the Erlang language server also verifies the Erlang/OTP runtime itself via _check_erlang_installation. If Erlang/OTP is missing or non-functional, __init__ raises RuntimeError directing you to the official Erlang downloads page, since the language server requires a working Erlang runtime.

Source

Thrown at src/solidlsp/language_servers/erlang_language_server.py:44

`#` was chosen because it cannot occur in an unquoted Erlang atom, so it can never collide with a
real function, type or macro name (unlike `@`, which is a legal atom character).
"""


class ErlangLanguageServer(SolidLanguageServer):
    """Language server for Erlang using Erlang LS."""

    def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
        """
        Creates an ErlangLanguageServer instance. This class is not meant to be instantiated directly.
        Use LanguageServer.create() instead.
        """
        self.erlang_ls_path = shutil.which("erlang_ls")
        if not self.erlang_ls_path:
            raise RuntimeError("Erlang LS not found. Install from: https://github.com/erlang-ls/erlang_ls")

        if not self._check_erlang_installation():
            raise RuntimeError("Erlang/OTP not found. Install from: https://www.erlang.org/downloads")

        super().__init__(
            config,
            repository_root_path,
            ProcessLaunchInfo(cmd=[self.erlang_ls_path, "--transport", "stdio"], cwd=repository_root_path),
            "erlang",
            solidlsp_settings,
        )

        # Add server readiness tracking like Elixir
        self.server_ready = threading.Event()

        # Set generous timeout for Erlang LS initialization
        self.set_request_timeout(120.0)

    @override
    def _document_symbols_cache_fingerprint(self) -> Hashable:
        normalize_symbol_name_version = 1

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Install Erlang/OTP: https://www.erlang.org/downloads (e.g., apt install erlang, brew install erlang)
  2. Verify with: erl -version (must succeed in the environment running Serena)
  3. If using asdf/kerl, activate the Erlang version so non-interactive shells see erl
  4. Reinstall erlang_ls if it was built against a removed OTP version

Example fix

// before
$ erl -version   # command not found
// after
$ apt-get install -y erlang
$ erl -version
Eshell V14.0
Defensive patterns

Strategy: validation

Validate before calling

import shutil, subprocess
def erlang_otp_available() -> bool:
    return shutil.which("erl") is not None and subprocess.run(
        ["erl", "+V"], capture_output=True
    ).returncode == 0

Type guard

def has_erlang() -> bool:
    import shutil
    return shutil.which("erl") is not None

Try / catch

try:
    server = LanguageServer.create(LanguageServerId.ERLANG, ...)
except RuntimeError as e:
    if "Erlang/OTP not found" in str(e):
        logger.error("Install Erlang/OTP: https://www.erlang.org/downloads")

Prevention

When it happens

Trigger: Creating an ErlangLanguageServer instance where erlang_ls is on PATH but the underlying `erl`/Erlang runtime check fails — Erlang not installed, broken OTP install, or erl not resolvable in the running environment.

Common situations: Installing only erlang-ls (which doesn't bundle OTP); Erlang removed during a system cleanup; kerl/asdf-managed Erlang not activated; minimal Docker images lacking the erlang runtime.

Related errors


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