{"record":{"id":"6efd524c3b382f2e","repo":"googleapis/mcp-toolbox","slug":"failed-to-unmarshal-json-w-body-s","errorCode":null,"errorMessage":"failed to unmarshal json: %w, body: %s","messagePattern":"failed to unmarshal json: %w, body: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/cloudmonitoring/cloud_monitoring.go","lineNumber":176,"sourceCode":"\t}\n\tdefer resp.Body.Close()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read response body: %w\", err)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"request failed: %s, body: %s\", resp.Status, string(body))\n\t}\n\n\tif len(body) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tvar result map[string]any\n\tif err := json.Unmarshal(body, &result); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to unmarshal json: %w, body: %s\", err, string(body))\n\t}\n\n\treturn result, nil\n}\n","sourceCodeStart":158,"sourceCodeEnd":181,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/cloudmonitoring/cloud_monitoring.go#L158-L181","documentation":"After a 200 response, RunQuery unmarshals the body into map[string]any. If the body is not valid JSON (or empty-but-nonzero garbage, HTML error pages from proxies, or truncated data), the unmarshal error plus the raw body are wrapped in this error.","triggerScenarios":"A successful (200) Cloud Monitoring response whose body fails json.Unmarshal — typically HTML/HTML-encoded proxy error pages, gzip content not decoded (missing Accept-Encoding handling), or truncated JSON.","commonSituations":"Corporate proxies injecting HTML login pages; misconfigured transports that don't decompress gzip responses; intermediary caching layers corrupting bodies.","solutions":["Inspect the body snippet in the error to identify what was actually returned","Verify no proxy/intermediary is substituting HTML responses for API JSON","Ensure the HTTP transport handles gzip/deflate correctly","Retry; if persistent, log the full response headers and escalate to the network owner"],"exampleFix":"// before\n// response is gzip-compressed, json.Unmarshal fails\nclient := &http.Client{}\n// after\ntransport := &http.Transport{DisableCompression: false}\nclient := &http.Client{Transport: transport} // Go auto-decompresses gzip","handlingStrategy":"type-guard","validationCode":"resp, err := http.Get(url)\nif err == nil {\n    ct := resp.Header.Get(\"Content-Type\")\n    if !strings.Contains(ct, \"application/json\") {\n        return fmt.Errorf(\"unexpected content-type %q; proxy may be intercepting\", ct)\n    }\n}","typeGuard":null,"tryCatchPattern":"result, err := src.RunQuery(ctx, query)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to unmarshal json\") {\n        log.Printf(\"non-JSON body returned (proxy/CDN issue?): %.200s\", err)\n        return fmt.Errorf(\"monitoring API returned invalid JSON; check proxies\")\n    }\n    return err\n}","preventionTips":["Ensure HTTP transports auto-decompress gzip","Bypass auth portals/captive proxies for googleapis.com","Log Content-Type headers when debugging","Pin DNS/hosts to avoid intercepted endpoints"],"tags":["json","cloud-monitoring","http"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}