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.
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)
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
- %d: %s
- failed to unmarshal quick Tunnel
- failed to marshal signPayload
- failed to send request
- 400 Bad Request
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/045ff90cd9a0e09e.
Report an issue: GitHub.