{"record":{"id":"7ae24ed28b7a9647","repo":"charmbracelet/crush","slug":"failed-to-get-mcp-states-status-code-d","errorCode":null,"errorMessage":"failed to get MCP states: status code %d","messagePattern":"failed to get MCP states: status code (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":322,"sourceCode":"\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)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get MCP pending auth: status code %d\", rsp.StatusCode)","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L304-L340","documentation":"MCPGetStates got a non-200 HTTP status from /workspaces/{id}/mcp/states. The server responded but rejected the request; the code is embedded in the message. Useful for distinguishing 404 (bad id) from 401 (auth) or 5xx (server fault).","triggerScenarios":"Calling MCPGetStates with an unknown workspace id (404), invalid/expired credentials (401/403), or when the server errors while collecting MCP states (500).","commonSituations":"Workspace recreated with a new id; auth token rotated; MCP state collection panicking server-side due to a broken MCP server config; old client hitting a restructured endpoint.","solutions":["Branch on the status code: 404 -> refresh workspace id; 401/403 -> re-auth; >=500 -> inspect server logs.","Validate the workspace id against a fresh GetWorkspace call before polling.","Fix any broken MCP server configuration server-side if 500s persist.","Update client/server to matching versions."],"exampleFix":"// before\nstates, err := client.MCPGetStates(ctx, wsID)\n// after\nstates, err := client.MCPGetStates(ctx, wsID)\nif err != nil {\n    var statusErr *statusCodeError // if you wrap status codes\n    if errors.As(err, &statusErr) && statusErr.code == http.StatusNotFound {\n        return nil, fmt.Errorf(\"workspace %s not found\", wsID)\n    }\n    return nil, err\n}","handlingStrategy":"fallback","validationCode":"if _, err := client.GetWorkspace(ctx, wsID); err != nil { return fmt.Errorf(\"cannot query MCP states: invalid workspace: %w\", err) }","typeGuard":"func statusCodeFrom(err error) int {\n\tvar se interface{ StatusCode() int }\n\tif err != nil && errors.As(err, &se) { return se.StatusCode() }\n\treturn 0\n}","tryCatchPattern":"states, err := client.MCPGetStates(ctx, wsID)\nif err != nil {\n\tswitch statusCodeFrom(err) {\n\tcase http.StatusNotFound: return nil, nil // no workspace/MCP states — treat as empty\n\tcase http.StatusUnauthorized: return nil, retryAfterAuth(ctx)\n\tdefault: return nil, err\n\t}\n}","preventionTips":["Refresh workspace ids when sessions restart instead of caching them.","Handle 404 as an empty-state signal rather than an error.","Re-authenticate automatically on 401/403.","Investigate server logs for 500s caused by broken MCP configs."],"tags":["http-status","mcp","api","go"],"backgroundTag":"http-non-200-status","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}