googleapis/mcp-toolbox · error
failed to decode response: %w
Error message
failed to decode response: %w
What it means
The API returned HTTP 200 but the response body could not be decoded into FetchQueryStatsResponse. The library streams the body through json.Decoder and wraps any decoding failure.
Source
Thrown at internal/sources/databaseinsights/databaseinsights.go:390
if err != nil {
return nil, fmt.Errorf("failed to create http request: %w", err)
}
httpReq.Header.Set("Content-Type", "application/json")
resp, err := s.httpClient.Do(httpReq)
if err != nil {
return nil, fmt.Errorf("failed to execute request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("request failed with status %s: %s", resp.Status, string(respBody))
}
var fetchResp FetchQueryStatsResponse
if err := json.NewDecoder(resp.Body).Decode(&fetchResp); err != nil {
return nil, fmt.Errorf("failed to decode response: %w", err)
}
return &fetchResp, nil
}
// FetchWaitEventStats executes the FetchWaitEventStats REST API method.
func (s *Source) FetchWaitEventStats(ctx context.Context, req *FetchWaitEventStatsRequest) (*FetchWaitEventStatsResponse, error) {
url := fmt.Sprintf("%s/v1beta/%s/waitEventStats:fetch", s.getEndpointForParent(req.Parent), req.Parent)
bodyBytes, err := json.Marshal(req)
if err != nil {
return nil, fmt.Errorf("failed to marshal request: %w", err)
}
httpReq, err := http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer(bodyBytes))
if err != nil {
return nil, fmt.Errorf("failed to create http request: %w", err)
}View on GitHub (pinned to 8cc6e09de2)
Solutions
- Capture and inspect the raw response body to see what was actually returned
- Verify no proxy/gateway is rewriting responses (test from the same host with curl)
- Check for API version changes and update the FetchQueryStatsResponse struct fields/types
- Add defensive checks for empty bodies before decoding
Example fix
// before
var fetchResp FetchQueryStatsResponse
json.NewDecoder(resp.Body).Decode(&fetchResp) // fails on empty/HTML body
// after
body, _ := io.ReadAll(resp.Body)
if len(bytes.TrimSpace(body)) == 0 { return nil, fmt.Errorf("empty response body") }
json.Unmarshal(body, &fetchResp) Defensive patterns
Strategy: type-guard
Validate before calling
// after a successful call, verify shape before use
func validFetchResp(r *FetchQueryStatsResponse) bool {
return r != nil // extend with required-field checks
} Type guard
func isDecodeError(err error) bool {
var ute *json.UnmarshalTypeError
var se *json.SyntaxError
return errors.As(err, new(*json.SyntaxError)) || errors.As(err, &ute) || errors.As(err, &se)
}
// usage: if isDecodeError(err) { inspect raw body / check API version } Try / catch
resp, err := src.FetchQueryStats(ctx, req)
if err != nil && strings.Contains(err.Error(), "failed to decode response") {
// capture raw body via a debug HTTP client, check for HTML proxy pages or schema drift
return fmt.Errorf("unexpected API response format: %w", err)
} Prevention
- Check response Content-Type is application/json before decoding
- Keep response structs in sync with the API version in use
- Route around proxies/gateways that rewrite error pages with 200 status
When it happens
Trigger: json.NewDecoder(resp.Body).Decode fails: body is not valid JSON, is truncated, is HTML from a proxy/error page, or has a schema that mismatches FetchQueryStatsResponse (e.g. a string where a number is expected).
Common situations: An intermediary (proxy/gateway) returned an HTML error page with 200; API version skew introducing new field types; truncated response from network issues; empty body.
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 body: %w
- params must be a valid JSON string: %w
- failed to marshal result: %w
- failed to parse introspection response: %w
- failed to decode Google tokeninfo response: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/b66b329962ebe58d.
Report an issue: GitHub.