Hmbown/CodeWhale · error

LSP diagnostics timed out sending document

Error message

LSP diagnostics timed out sending document

What it means

diagnostics_for sends a didOpen/didChange for the document and waits, under an overall deadline, for the language server to reply with publishDiagnostics. This error means the initial open_or_change send itself could not complete within the caller's deadline (the tokio timeout fired on the send future), so the function aborts instead of publishing stale or no diagnostics.

Solutions

  1. Increase the deadline passed to diagnostics_for so the send has time to complete
  2. Check that the language-server process is alive and responsive (logs, is_alive)
  3. Serialize diagnostics_for calls so one document's backpressure does not starve another's send
  4. If a server restart is suspected, reinitialize the client and retry

Example fix

// before
let diags = client.diagnostics_for(path, text, Duration::from_secs(2)).await;
// after
let diags = client.diagnostics_for(path, text, Duration::from_secs(10)).await;
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure a non-trivial deadline remains before calling
let deadline = Instant::now() + wait;
if deadline <= Instant::now() { bail!("deadline already expired"); }

Try / catch

match client.diagnostics_for(path, text, wait).await {
    Ok(d) => d,
    Err(e) if e.to_string().contains("timed out sending document") => {
        // extend budget / check server liveness, then retry once
        retry_with_longer_deadline()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling diagnostics_for with a deadline already exhausted or too short; open_or_change blocked because the diagnostics_gate or outbound queue is saturated by earlier documents; LSP server unresponsive so the send future stalls past the deadline.

Common situations: Large monorepos where the server is still indexing and backpressure delays didChange; opening a file right as a deadline-based caller (e.g. a test or UI wait) expires; a hung language-server child process.

Understand the failure class

Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/9b29a32bc83e358c. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/lsp/client.rs:394

    async fn diagnostics_for(
        &self,
        path: &Path,
        text: &str,
        wait: Duration,
    ) -> Result<DiagnosticPublication> {
        // One receiver cannot serve concurrent polling safely: serialize the
        // open/version/send/wait transaction, including semantic ensure_open.
        let deadline = tokio::time::Instant::now() + wait;
        let _gate = timeout(wait, self.diagnostics_gate.lock())
            .await
            .map_err(|_| anyhow!("LSP diagnostics timed out waiting for another document"))?;
        let path_buf = path.to_path_buf();
        let (_, version) = timeout(
            deadline.saturating_duration_since(tokio::time::Instant::now()),
            self.open_or_change(path, text),
        )
        .await
        .map_err(|_| anyhow!("LSP diagnostics timed out sending document"))??;
        loop {
            let remaining = deadline.saturating_duration_since(tokio::time::Instant::now());
            if remaining.is_zero() {
                return Err(anyhow!(
                    "LSP diagnostics timed out before a current publication"
                ));
            }
            let mut rx = self.diagnostics_rx.lock().await;
            let (file, published_version, items) = match timeout(remaining, rx.recv()).await {
                Ok(Some(item)) => item,
                Ok(None) => {
                    return Err(anyhow!(
                        "LSP diagnostics channel closed before publishDiagnostics"
                    ));
                }
                Err(_) => {
                    return Err(anyhow!(
                        "LSP diagnostics timed out before a current publication"

View on GitHub (pinned to 73e0f67d83)