charmbracelet/crush · error
failed to decode MCP prompt response: %w
Error message
failed to decode MCP prompt response: %w
What it means
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.
Source
Thrown at internal/client/config.go:358
// GetMCPPrompt retrieves a prompt from a named MCP server.
func (c *Client) GetMCPPrompt(ctx context.Context, id, clientID, promptID string, args map[string]string) (string, error) {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/get-prompt", id), nil, jsonBody(struct {
ClientID string `json:"client_id"`
PromptID string `json:"prompt_id"`
Args map[string]string `json:"args"`
}{ClientID: clientID, PromptID: promptID, Args: args}), http.Header{"Content-Type": []string{"application/json"}})
if err != nil {
return "", fmt.Errorf("failed to get MCP prompt: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return "", fmt.Errorf("failed to get MCP prompt: status code %d", rsp.StatusCode)
}
var result struct {
Prompt string `json:"prompt"`
}
if err := json.NewDecoder(rsp.Body).Decode(&result); err != nil {
return "", fmt.Errorf("failed to decode MCP prompt response: %w", err)
}
return result.Prompt, nil
}
View on GitHub (pinned to 7944b8e522)
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.
Example fix
// before: hard to see raw body on failure
var result struct {
Prompt string `json:"prompt"`
}
if err := json.NewDecoder(rsp.Body).Decode(&result); err != nil {
return "", fmt.Errorf("failed to decode MCP prompt response: %w", err)
}
// after: capture the body first for diagnosis
body, _ := io.ReadAll(rsp.Body)
var result struct {
Prompt string `json:"prompt"`
}
if err := json.Unmarshal(body, &result); err != nil {
return "", fmt.Errorf("failed to decode MCP prompt response: %w (body: %s)", err, truncate(body, 256))
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: confirm the endpoint returns JSON with a prompt field
resp, err := http.Get(mcpPromptURL)
if err == nil {
var probe map[string]json.RawMessage
if json.NewDecoder(resp.Body).Decode(&probe) != nil {
log.Println("MCP prompt endpoint does not return JSON")
}
if _, ok := probe["prompt"]; !ok {
log.Println("MCP prompt endpoint response missing 'prompt' field")
}
resp.Body.Close()
} Type guard
func isDecodeError(err error) bool {
var syn *json.SyntaxError
var typ *json.UnmarshalTypeError
return errors.As(err, &syn) || errors.As(err, &typ)
} Try / catch
prompt, err := client.GetMCPPrompt(ctx, name)
if err != nil {
var syn *json.SyntaxError
if errors.As(err, &syn) {
// Body wasn't JSON: likely a proxy or wrong endpoint
return fallbackPrompt(name)
}
return fmt.Errorf("getting MCP prompt: %w", err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to decode response: %w
- failed to decode MCP pending auth: %w
- failed to decode MCP auth URL: %w
- mcp http config requires a non-empty 'url' field
- failed to create OAuth handler for mcp %q: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/1a77f52d6fcca6b8.
Report an issue: GitHub.