charmbracelet/crush · error
failed to get LSPs: status code %d
Error message
failed to get LSPs: status code %d
What it means
GetLSPs got an HTTP response whose status code was not 200 from /workspaces/{id}/lsps. The server deliberately rejected the request; the numeric status is included in the message. No LSP state map is returned.
Source
Thrown at internal/client/proto.go:305
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)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get LSPs: status code %d", rsp.StatusCode)
}
var lsps map[string]proto.LSPClientInfo
if err := json.NewDecoder(rsp.Body).Decode(&lsps); err != nil {
return nil, fmt.Errorf("failed to decode LSPs: %w", err)
}
return lsps, nil
}
// MCPGetStates retrieves the MCP client states for a workspace.
func (c *Client) MCPGetStates(ctx context.Context, id string) (map[string]proto.MCPClientInfo, error) {
rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/mcp/states", id), nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to get MCP states: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to get MCP states: status code %d", rsp.StatusCode)
}View on GitHub (pinned to 7944b8e522)
Solutions
- Check the status code in the message and handle 404 by refreshing the workspace id (re-create or list workspaces).
- Re-authenticate for 401/403 responses.
- Restart the server / check server logs for 5xx errors.
- Align client and server versions so the endpoint exists.
Example fix
// before
lsps, err := client.GetLSPs(ctx, staleWsID)
// after
ws, err := client.GetWorkspace(ctx, currentWsID)
if err != nil { return nil, err }
lsps, err := client.GetLSPs(ctx, ws.ID)
if err != nil {
if isNotFoundStatus(err) { return nil, fmt.Errorf("workspace %s gone; re-open it", currentWsID) }
return nil, err
} Defensive patterns
Strategy: validation
Validate before calling
ws, err := client.GetWorkspace(ctx, wsID)
if err != nil { return fmt.Errorf("workspace %s invalid before GetLSPs: %w", wsID, err) } Type guard
func isNotFoundStatus(err error) bool {
var se interface{ StatusCode() int }
return err != nil && errors.As(err, &se) && (se.StatusCode() == 404 || se.StatusCode() == 410)
} Try / catch
lsps, err := client.GetLSPs(ctx, wsID)
if err != nil {
if isNotFoundStatus(err) {
return nil, ErrWorkspaceGone // caller recreates/reopens the workspace
}
return nil, err
} Prevention
- Always resolve the workspace id from a live session rather than caching it across restarts.
- Treat 404 as 're-open the workspace', not a fatal error.
- Re-authenticate on 401/403 before retrying.
- Check server logs when statuses are 5xx.
When it happens
Trigger: Calling GetLSPs/LSPGetStates with a nonexistent workspace id (404), expired auth (401/403), a server fault (500), or a client/server version mismatch where the lsps endpoint moved (404/405).
Common situations: Workspace closed/timed out on the server side; querying with an id from a previous session; reverse proxy returning 401; running an older client against a newer server.
Related errors
- failed to get LSP diagnostics: status code %d
- failed to get MCP states: status code %d
- failed to read file: %w
- failed to get LSP diagnostics: %w
- failed to decode LSP diagnostics: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/4eb2bdb81fafe33c.
Report an issue: GitHub.