{"record":{"id":"045ff90cd9a0e09e","repo":"cloudflare/cloudflared","slug":"failed-to-decode-http-response","errorCode":null,"errorMessage":"failed to decode HTTP response","messagePattern":"failed to decode HTTP response","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sshgen/sshgen.go","lineNumber":139,"sourceCode":"\n\tif err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to send request\")\n\t}\n\tdefer res.Body.Close()\n\n\tdecoder := json.NewDecoder(res.Body)\n\n\tif res.StatusCode != 200 {\n\t\tvar errResponse errorResponse\n\t\tif err := decoder.Decode(&errResponse); err != nil {\n\t\t\treturn \"\", err\n\t\t}\n\t\treturn \"\", fmt.Errorf(\"%d: %s\", errResponse.Status, errResponse.Message)\n\t}\n\n\tvar signRes signResponse\n\tif err := decoder.Decode(&signRes); err != nil {\n\t\treturn \"\", errors.Wrap(err, \"failed to decode HTTP response\")\n\t}\n\treturn signRes.Certificate, nil\n}\n\n// generateKeyPair creates a EC keypair (P256) and stores them in the homedir.\n// returns the generated public key from the successful keypair generation\nfunc generateKeyPair(fullName string) ([]byte, error) {\n\tpubKeyName := fullName + \".pub\"\n\n\texist, err := config.FileExists(pubKeyName)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif exist {\n\t\treturn os.ReadFile(pubKeyName)\n\t}\n\n\tkey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/cloudflare/cloudflared/blob/2253eeeb25a44a713a4b60b8ba1e1b3f377d1a0f/sshgen/sshgen.go#L121-L157","documentation":"After a successful (status 200) response, SignCert decodes the response body into a signResponse struct. This error means the 200 body was not valid JSON or did not match the expected shape, so the signed certificate could not be extracted.","triggerScenarios":"The cert_sign endpoint returns 200 with an empty, HTML, or otherwise malformed body; a proxy intercepts and rewrites the response.","commonSituations":"Captive portals or proxies returning HTML with status 200; Cloudflare API changes altering the response schema; truncated responses on flaky connections.","solutions":["Log/dump the raw response body to see what was actually returned","Confirm no proxy or captive portal is intercepting requests to the issuer domain","Update cloudflared — the sign endpoint response format may have changed","Retry the request; transient truncation can cause decode failures"],"exampleFix":"// before\nvar signRes signResponse\nif err := decoder.Decode(&signRes); err != nil {\n    return \"\", errors.Wrap(err, \"failed to decode HTTP response\")\n}\n// after\nvar signRes signResponse\nif err := decoder.Decode(&signRes); err != nil {\n    body, _ := io.ReadAll(res.Body)\n    return \"\", errors.Wrap(err, fmt.Sprintf(\"failed to decode HTTP response: %q\", string(body)))\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"cert, err := SignCert(token, pubKey)\nif err != nil && strings.Contains(err.Error(), \"failed to decode HTTP response\") {\n    // log raw body via a custom mockRequest to inspect actual response, then retry\n    log.Warn().Err(err).Msg(\"unexpected sign response; retrying\")\n    cert, err = SignCert(token, pubKey)\n}","preventionTips":["Route around proxies/captive portals that rewrite responses","Pin to a supported cloudflared version matching the current cert_sign API","Log response bodies on failure to diagnose schema drift"],"tags":["http","json","ssh"],"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"}