{"record":{"id":"1a77f52d6fcca6b8","repo":"charmbracelet/crush","slug":"failed-to-decode-mcp-prompt-response-w","errorCode":null,"errorMessage":"failed to decode MCP prompt response: %w","messagePattern":"failed to decode MCP prompt response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/config.go","lineNumber":358,"sourceCode":"// 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}\n\tvar result struct {\n\t\tPrompt string `json:\"prompt\"`\n\t}\n\tif err := json.NewDecoder(rsp.Body).Decode(&result); err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to decode MCP prompt response: %w\", err)\n\t}\n\treturn result.Prompt, nil\n}\n","sourceCodeStart":340,"sourceCodeEnd":362,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/config.go#L340-L362","documentation":"GetMCPPrompt fetches a prompt from the MCP server over HTTP and decodes the JSON body into a struct with a single `prompt` string field. This error means the response body was not valid JSON or did not match the expected shape. It wraps the underlying decoding error with %w so the root cause (syntax error, unexpected type, empty body) is preserved.","triggerScenarios":"Calling GetMCPPrompt when the server returns a 2xx response whose body is not decodable JSON containing a string `prompt` field — e.g. an HTML error page, empty body, truncated response, or a JSON object missing the `prompt` key.","commonSituations":"A reverse proxy or gateway returns an HTML error page with 200; the MCP server is an incompatible/older version returning a different schema; the response is cut off mid-stream; a misconfigured endpoint points at a non-MCP service.","solutions":["Inspect the wrapped error: a json.SyntaxError means the body is not JSON at all (check for a proxy/gateway intercepting the request).","Verify the URL points at the correct MCP server endpoint and version that returns {\"prompt\": \"...\"}.","Dump the raw response body (curl the endpoint) to see what is actually being returned.","Check network infrastructure (proxies, load balancers, auth layers) that could alter or truncate the response body."],"exampleFix":"// before: hard to see raw body on failure\nvar result struct {\n\tPrompt string `json:\"prompt\"`\n}\nif err := json.NewDecoder(rsp.Body).Decode(&result); err != nil {\n\treturn \"\", fmt.Errorf(\"failed to decode MCP prompt response: %w\", err)\n}\n// after: capture the body first for diagnosis\nbody, _ := io.ReadAll(rsp.Body)\nvar result struct {\n\tPrompt string `json:\"prompt\"`\n}\nif err := json.Unmarshal(body, &result); err != nil {\n\treturn \"\", fmt.Errorf(\"failed to decode MCP prompt response: %w (body: %s)\", err, truncate(body, 256))\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight: confirm the endpoint returns JSON with a prompt field\nresp, err := http.Get(mcpPromptURL)\nif err == nil {\n\tvar probe map[string]json.RawMessage\n\tif json.NewDecoder(resp.Body).Decode(&probe) != nil {\n\t\tlog.Println(\"MCP prompt endpoint does not return JSON\")\n\t}\n\tif _, ok := probe[\"prompt\"]; !ok {\n\t\tlog.Println(\"MCP prompt endpoint response missing 'prompt' field\")\n\t}\n\tresp.Body.Close()\n}","typeGuard":"func isDecodeError(err error) bool {\n\tvar syn *json.SyntaxError\n\tvar typ *json.UnmarshalTypeError\n\treturn errors.As(err, &syn) || errors.As(err, &typ)\n}","tryCatchPattern":"prompt, err := client.GetMCPPrompt(ctx, name)\nif err != nil {\n\tvar syn *json.SyntaxError\n\tif errors.As(err, &syn) {\n\t\t// Body wasn't JSON: likely a proxy or wrong endpoint\n\t\treturn fallbackPrompt(name)\n\t}\n\treturn fmt.Errorf(\"getting MCP prompt: %w\", err)\n}","preventionTips":["Pin the MCP server version to match the client's expected response schema.","Ensure no proxy/gateway sits between the client and the MCP server, or configure it to pass JSON through.","Log raw response bodies on decode failure to speed up diagnosis.","Validate the MCP server URL during configuration/startup with a smoke request."],"tags":["mcp","json","http","decoding"],"backgroundTag":"json-decode-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}