{"record":{"id":"3abec8b243447e9f","repo":"cloudflare/cloudflared","slug":"failed-to-decode-response","errorCode":null,"errorMessage":"failed to decode response","messagePattern":"failed to decode response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cfapi/base_client.go","lineNumber":116,"sourceCode":"\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"can't create %s request\", method)\n\t}\n\treq.Header.Set(\"User-Agent\", r.userAgent)\n\tif bodyReader != nil {\n\t\treq.Header.Set(\"Content-Type\", jsonContentType)\n\t}\n\treq.Header.Add(\"Authorization\", fmt.Sprintf(\"Bearer %s\", r.authToken))\n\treq.Header.Add(\"Accept\", \"application/json;version=1\")\n\treturn r.client.Do(req)\n}\n\nfunc parseResponseEnvelope(reader io.Reader) (*response, error) {\n\t// Schema for Tunnelstore responses in the v1 API.\n\t// Roughly, it's a wrapper around a particular result that adds failures/errors/etc\n\tvar result response\n\t// First, parse the wrapper and check the API call succeeded\n\tif err := json.NewDecoder(reader).Decode(&result); err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to decode response\")\n\t}\n\tif err := result.checkErrors(); err != nil {\n\t\treturn nil, err\n\t}\n\tif !result.Success {\n\t\treturn nil, ErrAPINoSuccess\n\t}\n\n\treturn &result, nil\n}\n\nfunc parseResponse(reader io.Reader, data interface{}) error {\n\tresult, err := parseResponseEnvelope(reader)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn parseResponseBody(result, data)","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/cfapi/base_client.go#L98-L134","documentation":"parseResponseEnvelope decodes the Cloudflare API response JSON envelope ({success, errors, messages, result}) and wraps json decode failures with this message. It means the response body was not valid JSON at all — the API (or an intermediary) returned HTML, an empty body, or truncated output.","triggerScenarios":"Receiving an HTML error page from a proxy/CDN, an empty response, a truncated body from network interruption, or hitting a non-Cloudflare-API endpoint that returns non-JSON.","commonSituations":"Corporate proxies or auth walls returning HTML login pages, Cloudflare WAF challenges, API downtime returning an error page, or TLS-intercepting middleboxes mangling responses.","solutions":["Log the raw response body and status code to see what was actually returned.","Verify you are reaching https://api.cloudflare.com and not a captive portal or proxy error page.","Retry the request — transient network truncation is a common cause.","If behind a corporate proxy, whitelist the API host or bypass the proxy for it."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var resp *cfapi.Route\nerr := retry(3, backoff, func() error {\n\tvar err error\n\tresp, err = client.GetRouteByIP(ctx, ip)\n\treturn err\n})\nif err != nil {\n\tlog.Error().Err(err).Msg(\"cfapi call failed after retries\")\n}","preventionTips":["Retry transient API calls with exponential backoff.","Monitor for proxies/WAFs injecting HTML into API responses.","Check response Content-Type is application/json when debugging."],"tags":["go","json","api-client","http-response"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f","analyzedAt":"2026-09-06T04:14:33.757Z","contentChangedAt":"2026-09-06T04:14:33.757Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}