{"record":{"id":"ab89e46e1ca5262b","repo":"googleapis/mcp-toolbox","slug":"could-not-unmarshal-response-as-json-w","errorCode":null,"errorMessage":"could not unmarshal response as json: %w","messagePattern":"could not unmarshal response as json: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/cloudhealthcare/cloud_healthcare.go","lineNumber":286,"sourceCode":"\t_, ok := s.allowedDICOMStores[storeID]\n\treturn ok\n}\n\nfunc (s *Source) UseClientAuthorization() bool {\n\treturn s.UseClientOAuth\n}\n\nfunc parseResults(resp *http.Response) (any, error) {\n\trespBytes, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"could not read response: %w\", err)\n\t}\n\tif resp.StatusCode > 299 {\n\t\treturn nil, fmt.Errorf(\"status %d %s: %s\", resp.StatusCode, resp.Status, respBytes)\n\t}\n\tvar jsonMap map[string]interface{}\n\tif err := json.Unmarshal(respBytes, &jsonMap); err != nil {\n\t\treturn nil, fmt.Errorf(\"could not unmarshal response as json: %w\", err)\n\t}\n\treturn jsonMap, nil\n}\n\nfunc (s *Source) getService(tokenStr string) (*healthcare.Service, error) {\n\tsvc := s.Service()\n\tvar err error\n\t// Initialize new service if using user OAuth token\n\tif s.UseClientAuthorization() {\n\t\tsvc, err = s.ServiceCreator()(tokenStr)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error creating service from OAuth access token: %w\", err)\n\t\t}\n\t}\n\treturn svc, nil\n}\n\nfunc isAlphanumeric(c byte) bool {","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/cloudhealthcare/cloud_healthcare.go#L268-L304","documentation":"parseResults successfully read the HTTP body but json.Unmarshal failed to decode it into a map[string]interface{}. The library expects every Cloud Healthcare API success response to be JSON; this error means the body was not valid JSON (or was JSON not shaped as an object, e.g. a bare array/string).","triggerScenarios":"GetFHIRResource, FHIRPatientSearch, FHIRPatientEverything or FHIRFetchPage receive a 2xx response whose body is HTML (proxy/login page), empty, truncated, or a JSON array/other non-object type, so json.Unmarshal into map[string]interface{} errors.","commonSituations":"A corporate proxy or load balancer intercepting the request and returning an HTML error page with 200; a misconfigured binary/DICOM response being read through the FHIR path; Google returning an NDJSON stream (search-with-post returning concatenated JSON) that is not a single object.","solutions":["Log the raw respBytes to see what non-JSON content is actually being returned","Check for an intercepting proxy/CDN returning HTML — bypass it or add it to NO_PROXY","If a DICOM/binary payload is expected, use the DICOM-specific tooling instead of the FHIR JSON path","For NDJSON responses, switch to a decoder that reads a stream of objects (json.Decoder in a loop) instead of one Unmarshal"],"exampleFix":"// before\nvar jsonMap map[string]interface{}\nif err := json.Unmarshal(respBytes, &jsonMap); err != nil {\n    return nil, fmt.Errorf(\"could not unmarshal response as json: %w\", err)\n}\n// after (handles ndjson streams too)\ndec := json.NewDecoder(bytes.NewReader(respBytes))\nvar jsonMap map[string]interface{}\nif err := dec.Decode(&jsonMap); err != nil {\n    return nil, fmt.Errorf(\"could not unmarshal response as json (body: %.200s): %w\", respBytes, err)\n}","handlingStrategy":"type-guard","validationCode":"function looksLikeJSON(s) { const t = s.trim(); return t.startsWith('{') || t.startsWith('['); }","typeGuard":"function isFHIRJSONObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v) && (v.resourceType !== undefined || v.total !== undefined); }","tryCatchPattern":"try {\n  const result = await tool.invoke({ query });\n  if (!isFHIRJSONObject(result)) throw new Error('Unexpected response shape: ' + JSON.stringify(result).slice(0, 200));\n} catch (e) {\n  if (/could not unmarshal response as json/.test(e.message)) {\n    // inspect raw body in the message; check for proxy/HTML interception\n  }\n  throw e;\n}","preventionTips":["Ensure no corporate proxy intercepts *.googleapis.com traffic with HTML pages","Do not route binary/DICOM responses through JSON-parsing FHIR tools","Handle NDJSON (search-with-post) streams with a streaming decoder, not a single Unmarshal"],"tags":["json","unmarshal","google-cloud","healthcare-api"],"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"}