{"record":{"id":"29473b5853a6783c","repo":"charmbracelet/crush","slug":"failed-to-refresh-mcp-prompts-w","errorCode":null,"errorMessage":"failed to refresh MCP prompts: %w","messagePattern":"failed to refresh MCP prompts: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":399,"sourceCode":"\tif rsp.StatusCode != http.StatusOK {\n\t\tvar e proto.Error\n\t\tif err := json.NewDecoder(rsp.Body).Decode(&e); err == nil && e.Message != \"\" {\n\t\t\treturn fmt.Errorf(\"failed to authenticate MCP: %s\", e.Message)\n\t\t}\n\t\treturn fmt.Errorf(\"failed to authenticate MCP: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// MCPRefreshPrompts refreshes prompts for a named MCP client.\nfunc (c *Client) MCPRefreshPrompts(ctx context.Context, id, name string) error {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/mcp/refresh-prompts\", id), nil,\n\t\tjsonBody(struct {\n\t\t\tName string `json:\"name\"`\n\t\t}{Name: name}),\n\t\thttp.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to refresh MCP prompts: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to refresh MCP prompts: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// MCPRefreshResources refreshes resources for a named MCP client.\nfunc (c *Client) MCPRefreshResources(ctx context.Context, id, name string) error {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/mcp/refresh-resources\", id), nil,\n\t\tjsonBody(struct {\n\t\t\tName string `json:\"name\"`\n\t\t}{Name: name}),\n\t\thttp.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to refresh MCP resources: %w\", err)\n\t}","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L381-L417","documentation":"This error is returned by Client.MCPRefreshPrompts when the HTTP POST to /workspaces/{id}/mcp/refresh-prompts fails before a response is available. The underlying transport error (connection refused, DNS failure, timeout, cancelled context) is wrapped with %w. It means the refresh-prompts request never got a response from the server.","triggerScenarios":"Calling MCPRefreshPrompts(ctx, id, name) while the server is unreachable, the network drops mid-request, TLS handshake fails, the base URL is misconfigured, or ctx is cancelled before the POST completes.","commonSituations":"Server restarted while the client was connected; laptop switching networks/VPNs; wrong port in client config; context deadline exceeded when the MCP server's prompt discovery is slow upstream.","solutions":["Inspect the wrapped error to identify whether it is a connection, DNS, TLS, or context failure","Verify the API server is running and reachable at the configured base URL","Retry the call with a fresh, adequately-long context after connectivity is restored","Confirm the workspace id and MCP name exist; fix client configuration if the endpoint host/port is wrong"],"exampleFix":"// before\nerr := client.MCPRefreshPrompts(ctx, \"ws-123\", \"github\") // fires even when offline\n\n// after\nif err := pingEndpoint(ctx); err != nil {\n    return fmt.Errorf(\"server unreachable, skipping prompt refresh: %w\", err)\n}\nif err := client.MCPRefreshPrompts(ctx, \"ws-123\", \"github\"); err != nil {\n    return fmt.Errorf(\"refresh prompts: %w\", err)\n}","handlingStrategy":"retry","validationCode":"// Confirm connectivity and a live context before refreshing\nfunc readyToRefresh(ctx context.Context, baseURL string) error {\n    if err := ctx.Err(); err != nil { return fmt.Errorf(\"context not usable: %w\", err) }\n    return serverReachable(ctx, baseURL) // HEAD probe with short timeout\n}","typeGuard":"// Detect transport-level causes in the wrapped error\nfunc isRefreshTransportErr(err error) bool {\n    var netErr net.Error\n    return err != nil && strings.HasPrefix(err.Error(), \"failed to refresh MCP prompts: \") &&\n        (errors.As(err, &netErr) || errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled))\n}","tryCatchPattern":"// Bounded retry for transient transport failures\nerr := client.MCPRefreshPrompts(ctx, wsID, name)\nfor attempt := 0; err != nil && isRefreshTransportErr(err) && attempt < 3; attempt++ {\n    time.Sleep(time.Duration(1<<attempt) * time.Second)\n    err = client.MCPRefreshPrompts(ctx, wsID, name)\n}\nif err != nil { return fmt.Errorf(\"prompt refresh: %w\", err) }","preventionTips":["Schedule prompt refresh with a generous context timeout; upstream MCP discovery can be slow","Probe server health before issuing refresh calls after connectivity changes","Serialize refresh calls per MCP server to avoid timeouts from concurrent upstream load","Keep the client base URL/port configuration in sync with the running server version"],"tags":["network","http","mcp","context"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}