cloudflare/cloudflared · error
failed to decode HTTP response
Error message
failed to decode HTTP response
What it means
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.
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
Example fix
// before
var signRes signResponse
if err := decoder.Decode(&signRes); err != nil {
return "", errors.Wrap(err, "failed to decode HTTP response")
}
// after
var signRes signResponse
if err := decoder.Decode(&signRes); err != nil {
body, _ := io.ReadAll(res.Body)
return "", errors.Wrap(err, fmt.Sprintf("failed to decode HTTP response: %q", string(body)))
} Defensive patterns
Strategy: retry
Try / catch
cert, err := SignCert(token, pubKey)
if err != nil && strings.Contains(err.Error(), "failed to decode HTTP response") {
// log raw body via a custom mockRequest to inspect actual response, then retry
log.Warn().Err(err).Msg("unexpected sign response; retrying")
cert, err = SignCert(token, pubKey)
} Prevention
- 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
When it happens
Trigger: The cert_sign endpoint returns 200 with an empty, HTML, or otherwise malformed body; a proxy intercepts and rewrites the response.
Common situations: Captive portals or proxies returning HTML with status 200; Cloudflare API changes altering the response schema; truncated responses on flaky connections.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- 400 Bad Request
- %d: %s
- failed to marshal signPayload
- failed to send request
- failed to unmarshal quick Tunnel
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/045ff90cd9a0e09e.
Report an issue: GitHub.
Appendix: source
Thrown at sshgen/sshgen.go:139
if err != nil {
return "", errors.Wrap(err, "failed to send request")
}
defer res.Body.Close()
decoder := json.NewDecoder(res.Body)
if res.StatusCode != 200 {
var errResponse errorResponse
if err := decoder.Decode(&errResponse); err != nil {
return "", err
}
return "", fmt.Errorf("%d: %s", errResponse.Status, errResponse.Message)
}
var signRes signResponse
if err := decoder.Decode(&signRes); err != nil {
return "", errors.Wrap(err, "failed to decode HTTP response")
}
return signRes.Certificate, nil
}
// generateKeyPair creates a EC keypair (P256) and stores them in the homedir.
// returns the generated public key from the successful keypair generation
func generateKeyPair(fullName string) ([]byte, error) {
pubKeyName := fullName + ".pub"
exist, err := config.FileExists(pubKeyName)
if err != nil {
return nil, err
}
if exist {
return os.ReadFile(pubKeyName)
}
key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)View on GitHub (pinned to 2253eeeb25)