{"record":{"id":"e7a86a006de99e0b","repo":"charmbracelet/crush","slug":"failed-to-get-mcp-states-w","errorCode":null,"errorMessage":"failed to get MCP states: %w","messagePattern":"failed to get MCP states: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":318,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get LSPs: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get LSPs: status code %d\", rsp.StatusCode)\n\t}\n\tvar lsps map[string]proto.LSPClientInfo\n\tif err := json.NewDecoder(rsp.Body).Decode(&lsps); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode LSPs: %w\", err)\n\t}\n\treturn lsps, nil\n}\n\n// MCPGetStates retrieves the MCP client states for a workspace.\nfunc (c *Client) MCPGetStates(ctx context.Context, id string) (map[string]proto.MCPClientInfo, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/mcp/states\", id), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get MCP states: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get MCP states: status code %d\", rsp.StatusCode)\n\t}\n\tvar states map[string]proto.MCPClientInfo\n\tif err := json.NewDecoder(rsp.Body).Decode(&states); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode MCP states: %w\", err)\n\t}\n\treturn states, nil\n}\n\n// MCPPendingAuth retrieves the MCP servers awaiting OAuth authentication\n// for a workspace.\nfunc (c *Client) MCPPendingAuth(ctx context.Context, id string) ([]proto.MCPPendingAuthServer, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/mcp/pending-auth\", id), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get MCP pending auth: %w\", err)","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L300-L336","documentation":"MCPGetStates issues GET /workspaces/{id}/mcp/states and wraps any transport failure from c.get. The HTTP request never completed — no status code exists. This reports connectivity, not MCP configuration problems.","triggerScenarios":"Calling MCPGetStates(ctx, id) when the server socket is closed, the base URL is misconfigured, the connection resets, or ctx is canceled/expired during the call.","commonSituations":"Crush daemon stopped while a client polls MCP states; wrong host/port config; firewall blocking localhost or remote server; context deadline too tight for a busy server.","solutions":["Read the wrapped cause (errors.Unwrap) and fix it — usually restart the server or correct the address.","Verify server reachability with a simple request (curl the base URL).","Check workspace id validity in the path.","Use a longer-lived context or add retry with backoff for transient failures."],"exampleFix":"// before\nstates, err := client.MCPGetStates(ctx, wsID)\nif err != nil { return err }\n// after\nstates, err := client.MCPGetStates(ctx, wsID)\nif err != nil {\n    if isConnRefused(err) { return fmt.Errorf(\"crush server not reachable; start it before polling MCP states\") }\n    return err\n}","handlingStrategy":"retry","validationCode":"resp, err := http.Get(baseURL + \"/health\")\nif err != nil || resp.StatusCode != 200 { return errors.New(\"crush server not reachable before MCPGetStates\") }","typeGuard":"func isConnRefused(err error) bool {\n\treturn errors.Is(err, syscall.ECONNREFUSED) || strings.Contains(err.Error(), \"connection refused\")\n}","tryCatchPattern":"states, err := client.MCPGetStates(ctx, wsID)\nif err != nil {\n\tif isConnRefused(err) { return nil, ErrServerDown } // upstream: restart server and retry\n\treturn nil, err\n}","preventionTips":["Poll a health endpoint before calling MCP state APIs.","Use exponential backoff so a downed server isn't hammered.","Keep contexts alive long enough for slow MCP state collection.","Check firewall/DNS when the server runs remotely."],"tags":["network","http-client","mcp","go"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}