{"record":{"id":"b66b329962ebe58d","repo":"googleapis/mcp-toolbox","slug":"failed-to-decode-response-w","errorCode":null,"errorMessage":"failed to decode response: %w","messagePattern":"failed to decode response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/databaseinsights/databaseinsights.go","lineNumber":390,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create http request: %w\", err)\n\t}\n\thttpReq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := s.httpClient.Do(httpReq)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\trespBody, _ := io.ReadAll(resp.Body)\n\t\treturn nil, fmt.Errorf(\"request failed with status %s: %s\", resp.Status, string(respBody))\n\t}\n\n\tvar fetchResp FetchQueryStatsResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&fetchResp); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode response: %w\", err)\n\t}\n\n\treturn &fetchResp, nil\n}\n\n// FetchWaitEventStats executes the FetchWaitEventStats REST API method.\nfunc (s *Source) FetchWaitEventStats(ctx context.Context, req *FetchWaitEventStatsRequest) (*FetchWaitEventStatsResponse, error) {\n\turl := fmt.Sprintf(\"%s/v1beta/%s/waitEventStats:fetch\", s.getEndpointForParent(req.Parent), req.Parent)\n\n\tbodyBytes, err := json.Marshal(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal request: %w\", err)\n\t}\n\n\thttpReq, err := http.NewRequestWithContext(ctx, \"POST\", url, bytes.NewBuffer(bodyBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create http request: %w\", err)\n\t}","sourceCodeStart":372,"sourceCodeEnd":408,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/databaseinsights/databaseinsights.go#L372-L408","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nvar fetchResp FetchQueryStatsResponse\njson.NewDecoder(resp.Body).Decode(&fetchResp) // fails on empty/HTML body\n// after\nbody, _ := io.ReadAll(resp.Body)\nif len(bytes.TrimSpace(body)) == 0 { return nil, fmt.Errorf(\"empty response body\") }\njson.Unmarshal(body, &fetchResp)","handlingStrategy":"type-guard","validationCode":"// after a successful call, verify shape before use\nfunc validFetchResp(r *FetchQueryStatsResponse) bool {\n  return r != nil // extend with required-field checks\n}","typeGuard":"func isDecodeError(err error) bool {\n  var ute *json.UnmarshalTypeError\n  var se *json.SyntaxError\n  return errors.As(err, new(*json.SyntaxError)) || errors.As(err, &ute) || errors.As(err, &se)\n}\n// usage: if isDecodeError(err) { inspect raw body / check API version }","tryCatchPattern":"resp, err := src.FetchQueryStats(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"failed to decode response\") {\n  // capture raw body via a debug HTTP client, check for HTML proxy pages or schema drift\n  return fmt.Errorf(\"unexpected API response format: %w\", err)\n}","preventionTips":["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"],"tags":["json","response-parsing","rest"],"backgroundTag":"json-decode-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}