Kuberwastaken/claurst · error · anyhow::Error

LSP server ' ' not running

Error message

LSP server '{}' not running

What it means

Thrown in `LspManager::hover` when the resolved server name has no entry in `self.clients` even after `ensure_started`. ensure_started silently continues when a server fails to spawn or fail to initialize (it only logs a warning), so the subsequent clients.get() finds nothing. It indicates the language server process is not running.

Solutions

  1. Verify the server binary is installed and on PATH (e.g. `which rust-analyzer`).
  2. Inspect logs for the preceding "Failed to start/initialize LSP server" warnings to find the root cause.
  3. Call ensure_started / reopen the manager and retry; add explicit startup error propagation instead of warn-and-continue.
  4. Validate root_dir exists and initializationOptions are accepted by the server.

Example fix

// before: assume startup succeeded
manager.ensure_started(path, root).await?;
let hover = manager.hover(path, root, line, col).await?;
// after: surface startup failures before feature calls
manager.ensure_started(path, root).await.map_err(|e| {
    anyhow::anyhow!("LSP startup failed for {}: {e}", path)
})?;
let hover = manager.hover(path, root, line, col).await?;
Defensive patterns

Strategy: retry

Validate before calling

// ensure the server binary is invocable before feature calls
let ok = std::process::Command::new(&config.command).arg("--version").output().is_ok();
if !ok { bail!("LSP server '{}' unavailable", config.name); }

Type guard

fn server_running(manager: &LspManager, name: &str) -> bool {
    manager.clients.contains_key(name)
}

Try / catch

let hover = match manager.hover(path, root, line, col).await {
    Ok(h) => h,
    Err(e) if e.to_string().contains("not running") => {
        manager.ensure_started(path, root).await?;
        manager.hover(path, root, line, col).await.unwrap_or(None)
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: hover() where ensure_started failed to spawn the server binary (command not found) or the initialize handshake failed, leaving clients without the named entry.

Common situations: Server binary not installed or not on PATH; server crashed during startup; initialize failed due to bad rootUri or initializationOptions; startup raced with the request in an async context.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/a322814f8b72c8a0. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/core/src/lsp.rs:1117

    pub async fn hover(
        &mut self,
        file_path: &str,
        root_dir: &Path,
        line: u32,
        character: u32,
    ) -> anyhow::Result<Option<String>> {
        let uri = path_to_uri(file_path);
        let server_name = self
            .server_name_for_file(file_path)
            .ok_or_else(|| {
                anyhow::anyhow!("No LSP server configured for '{}'", file_path)
            })?
            .to_string();
        self.ensure_started(file_path, root_dir).await?;
        let client = self
            .clients
            .get(&server_name)
            .ok_or_else(|| anyhow::anyhow!("LSP server '{}' not running", server_name))?;
        client.hover(&uri, line, character).await
    }

    /// Get definition locations for `file_path` at the given 1-based position.
    pub async fn definition(
        &mut self,
        file_path: &str,
        root_dir: &Path,
        line: u32,
        character: u32,
    ) -> anyhow::Result<Vec<String>> {
        let uri = path_to_uri(file_path);
        let server_name = self
            .server_name_for_file(file_path)
            .ok_or_else(|| {
                anyhow::anyhow!("No LSP server configured for '{}'", file_path)
            })?
            .to_string();

View on GitHub (pinned to b0637c97ec)