{"record":{"id":"57d9b700ae6ed4ec","repo":"charmbracelet/crush","slug":"failed-to-decode-mcp-prompts-w","errorCode":null,"errorMessage":"failed to decode MCP prompts: %w","messagePattern":"failed to decode MCP prompts: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/config.go","lineNumber":335,"sourceCode":"\tvar contents []MCPResourceContents\n\tif err := json.NewDecoder(rsp.Body).Decode(&contents); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode MCP resource: %w\", err)\n\t}\n\treturn contents, nil\n}\n\nfunc (c *Client) ListMCPPrompts(ctx context.Context, id string) ([]proto.MCPPrompt, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/mcp/prompts\", id), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to list MCP prompts: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to list MCP prompts: status code %d\", rsp.StatusCode)\n\t}\n\tvar prompts []proto.MCPPrompt\n\tif err := json.NewDecoder(rsp.Body).Decode(&prompts); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode MCP prompts: %w\", err)\n\t}\n\treturn prompts, nil\n}\n\n// GetMCPPrompt retrieves a prompt from a named MCP server.\nfunc (c *Client) GetMCPPrompt(ctx context.Context, id, clientID, promptID string, args map[string]string) (string, error) {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/mcp/get-prompt\", id), nil, jsonBody(struct {\n\t\tClientID string            `json:\"client_id\"`\n\t\tPromptID string            `json:\"prompt_id\"`\n\t\tArgs     map[string]string `json:\"args\"`\n\t}{ClientID: clientID, PromptID: promptID, Args: args}), http.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get MCP prompt: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn \"\", fmt.Errorf(\"failed to get MCP prompt: status code %d\", rsp.StatusCode)\n\t}","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/config.go#L317-L353","documentation":"On a 200 response, ListMCPPrompts decodes the body into []proto.MCPPrompt. 'failed to decode MCP prompts: %w' means the JSON body does not match the expected prompt schema — typically a client/server version mismatch or an intermediary returning non-JSON content.","triggerScenarios":"json.Decode error: schema drift in proto.MCPPrompt, HTML error page from a proxy, empty or truncated body despite 200.","commonSituations":"Upgraded Coder server with a changed prompt schema while the client is old; an ingress proxy returning HTML 200 pages; custom MCP servers emitting unexpected prompt fields is fine, but a wholly different body shape is not.","solutions":["Align client and server versions.","Inspect the raw body (curl the endpoint) to confirm what was returned.","Bypass/check proxies to rule out HTML injection.","Update the client's proto.MCPPrompt types if the schema legitimately changed."],"exampleFix":"// before\nprompts, err := client.ListMCPPrompts(ctx, id)\n// after\nprompts, err := client.ListMCPPrompts(ctx, id)\nif err != nil && strings.Contains(err.Error(), \"failed to decode MCP prompts\") {\n    return nil, fmt.Errorf(\"prompt schema mismatch — update the coder client to match server version: %w\", err)\n}","handlingStrategy":"type-guard","validationCode":"// check version compatibility once at startup\ninfo, err := client.BuildInfo(ctx)\nif err != nil {\n    return fmt.Errorf(\"cannot verify server compatibility: %w\", err)\n}","typeGuard":"func isPromptDecodeError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"failed to decode MCP prompts\")\n}\n// usage: if isPromptDecodeError(err) { /* version mismatch — do not retry blindly */ }","tryCatchPattern":"prompts, err := client.ListMCPPrompts(ctx, id)\nif isPromptDecodeError(err) {\n    // schema mismatch: update client types or server version; don't retry\n    return nil, fmt.Errorf(\"prompt schema mismatch with server: %w\", err)\n}\nif err != nil { return nil, err }","preventionTips":["Upgrade the client whenever the server is upgraded.","Treat decode errors as non-retryable and investigate the raw body.","Confirm proxies return JSON, not HTML error pages.","Add integration tests hitting a real server to catch schema drift early."],"tags":["json","decoding","version-skew"],"backgroundTag":"json-decode-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}