charmbracelet/crush · error

failed to get LSP diagnostics: %w

Error message

failed to get LSP diagnostics: %w

What it means

Client.GetLSPDiagnostics issues GET /workspaces/{id}/lsps/{lspName}/diagnostics and wraps any transport-level failure from the HTTP helper (c.get) with this message. It means the request to the crush server never produced an HTTP response (connection failure, bad URL, canceled context, etc.), not that diagnostics are missing. The underlying cause is always available in the wrapped %w error.

Source

Thrown at internal/client/proto.go:284

}

func sendEvent(ctx context.Context, evc chan any, ev any) bool {
	if ctx.Err() != nil {
		return false
	}
	select {
	case evc <- ev:
		return true
	case <-ctx.Done():
		return false
	}
}

// GetLSPDiagnostics retrieves LSP diagnostics for a specific LSP client.
func (c *Client) GetLSPDiagnostics(ctx context.Context, id string, lspName string) (map[protocol.DocumentURI][]protocol.Diagnostic, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/lsps/%s/diagnostics", id, lspName), nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get LSP diagnostics: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to get LSP diagnostics: status code %d", rsp.StatusCode)
	}
	var diagnostics map[protocol.DocumentURI][]protocol.Diagnostic
	if err := json.NewDecoder(rsp.Body).Decode(&diagnostics); err != nil {
		return nil, fmt.Errorf("failed to decode LSP diagnostics: %w", err)
	}
	return diagnostics, nil
}

// GetLSPs retrieves the LSP client states for a workspace.
func (c *Client) GetLSPs(ctx context.Context, id string) (map[string]proto.LSPClientInfo, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/lsps", id), nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get LSPs: %w", err)
	}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Check the wrapped cause in errors.Unwrap / %v output and fix the underlying transport issue (server down, wrong address).
  2. Verify the crush server/daemon is running and reachable at the configured base URL.
  3. Confirm the workspace id and lspName used in the URL path are correct.
  4. Ensure ctx isn't already canceled/expired before the call; increase timeouts if requests are being dropped.

Example fix

// before
if !isServerRunning() { /* proceed anyway */ }
diags, err := client.GetLSPDiagnostics(ctx, wsID, "gopls")
// after
if !isServerRunning() { return nil, fmt.Errorf("crush server not running at %s", baseURL) }
ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
defer cancel()
diags, err := client.GetLSPDiagnostics(ctx, wsID, "gopls")
if err != nil { return nil, fmt.Errorf("GetLSPDiagnostics: %w", err) }
Defensive patterns

Strategy: try-catch

Validate before calling

if !serverReachable(baseURL) { return fmt.Errorf("crush server unreachable at %s", baseURL) }
if wsID == "" || lspName == "" { return errors.New("workspace id and lsp name are required") }

Type guard

func isTransportErr(err error) bool {
	var ne net.Error
	return err != nil && (errors.As(err, &ne) || errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded))
}

Try / catch

diags, err := client.GetLSPDiagnostics(ctx, wsID, lspName)
if err != nil {
	if isTransportErr(err) {
		// server down / network issue — surface or retry with backoff
		return nil, fmt.Errorf("LSP diagnostics unavailable: %w", err)
	}
	return nil, err
}

Prevention

When it happens

Trigger: Calling GetLSPDiagnostics(ctx, id, lspName) when the server is unreachable, the base URL/host is wrong, the connection is refused or reset, the TLS handshake fails, or ctx is canceled before the response arrives.

Common situations: Running the client against a daemon that isn't started or has exited; pointing the client at the wrong port; a stale workspace id causing a redirect/proxy failure; network interruption between client and server; test environments with no local server.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/3792096edfd6da19. Report an issue: GitHub.