charmbracelet/crush · error
failed to decode MCP resource: %w
Error message
failed to decode MCP resource: %w
What it means
After a successful 200 response, ReadMCPResource decodes the body into []MCPResourceContents. 'failed to decode MCP resource: %w' means the body was not the expected JSON array — a client/server API mismatch or a proxy HTML error page.
Source
Thrown at internal/client/config.go:319
return nil
}
// ReadMCPResource reads a resource from a named MCP server.
func (c *Client) ReadMCPResource(ctx context.Context, id, name, uri string) ([]MCPResourceContents, error) {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/mcp/read-resource", id), nil, jsonBody(struct {
Name string `json:"name"`
URI string `json:"uri"`
}{Name: name, URI: uri}), http.Header{"Content-Type": []string{"application/json"}})
if err != nil {
return nil, fmt.Errorf("failed to read MCP resource: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to read MCP resource: status code %d", rsp.StatusCode)
}
var contents []MCPResourceContents
if err := json.NewDecoder(rsp.Body).Decode(&contents); err != nil {
return nil, fmt.Errorf("failed to decode MCP resource: %w", err)
}
return contents, nil
}
func (c *Client) ListMCPPrompts(ctx context.Context, id string) ([]proto.MCPPrompt, error) {
rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/mcp/prompts", id), nil, nil)
if err != nil {
return nil, fmt.Errorf("failed to list MCP prompts: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("failed to list MCP prompts: status code %d", rsp.StatusCode)
}
var prompts []proto.MCPPrompt
if err := json.NewDecoder(rsp.Body).Decode(&prompts); err != nil {
return nil, fmt.Errorf("failed to decode MCP prompts: %w", err)
}
return prompts, nilView on GitHub (pinned to 7944b8e522)
Solutions
- Check client/server version compatibility and align versions.
- Dump the raw response body (curl the endpoint) to see what was actually returned.
- Confirm no proxy is mangling responses (look for HTML in the error).
- Retry; transient truncation can also cause decode failures.
Example fix
// before
contents, err := client.ReadMCPResource(ctx, id, name, uri)
// after
contents, err := client.ReadMCPResource(ctx, id, name, uri)
if err != nil && strings.Contains(err.Error(), "failed to decode MCP resource") {
return nil, fmt.Errorf("incompatible server response for resource %q — verify client/server versions: %w", uri, err)
} Defensive patterns
Strategy: type-guard
Validate before calling
// sanity-check client/server compatibility at startup
ver, err := client.BuildInfo(ctx)
if err != nil || !compatibleVersions(clientVersion, ver.ExternalURL) {
return errors.New("coder client and server versions are incompatible")
} Type guard
func isDecodeError(err error) bool {
return err != nil && strings.Contains(err.Error(), "failed to decode MCP resource")
}
// usage: if isDecodeError(err) { /* treat as schema/proxy mismatch, not transient */ } Try / catch
contents, err := client.ReadMCPResource(ctx, id, name, uri)
if isDecodeError(err) {
// non-retryable: inspect raw response, check versions, rule out proxies
return nil, fmt.Errorf("unexpected response shape from server: %w", err)
}
if err != nil { return nil, err } Prevention
- Keep client and server versions aligned.
- Verify no auth proxy or WAF returns HTML with 200 status.
- When upgrading the server, regenerate/update client types.
- Spot-check the endpoint with curl after server upgrades.
When it happens
Trigger: json.Decode fails: server returned a different schema (version skew), an HTML error page from a reverse proxy, truncated body, or empty response.
Common situations: Client and Coder server versions out of sync; an auth proxy or load balancer intercepting and returning HTML; resource contents shape changed in a newer server release.
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 MCP prompts: %w
- failed to decode response: %w
- failed to decode MCP prompt response: %w
- failed to decode workspaces: %w
- failed to decode MCP pending auth: %w
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/07593c2fc6dfe76f.
Report an issue: GitHub.