caddyserver/caddy · error

decoding API response: %v

Error message

decoding API response: %v

What it means

ZeroSSL's EAB endpoint returned a body that could not be JSON-decoded into the expected {success, error, eab_kid, eab_hmac_key} structure. The request itself succeeded (status received), but the payload was not valid JSON — e.g. an HTML error page from a proxy, an empty body, or truncated response.

Source

Thrown at modules/caddytls/acmeissuer.go:402

	resp, err := http.DefaultClient.Do(req) //nolint:gosec // no SSRF since URL is from trusted config
	if err != nil {
		return nil, acct, fmt.Errorf("performing EAB credentials request: %v", err)
	}
	defer resp.Body.Close()

	var result struct {
		Success bool `json:"success"`
		Error   struct {
			Code int    `json:"code"`
			Type string `json:"type"`
		} `json:"error"`
		EABKID     string `json:"eab_kid"`
		EABHMACKey string `json:"eab_hmac_key"`
	}
	err = json.NewDecoder(resp.Body).Decode(&result)
	if err != nil {
		return nil, acct, fmt.Errorf("decoding API response: %v", err)
	}
	if result.Error.Code != 0 {
		// do this check first because ZeroSSL's API returns 200 on errors
		return nil, acct, fmt.Errorf("failed getting EAB credentials: HTTP %d: %s (code %d)",
			resp.StatusCode, result.Error.Type, result.Error.Code)
	}
	if resp.StatusCode != http.StatusOK {
		return nil, acct, fmt.Errorf("failed getting EAB credentials: HTTP %d", resp.StatusCode)
	}

	if c := iss.logger.Check(zapcore.InfoLevel, "generated EAB credentials"); c != nil {
		c.Write(zap.String("key_id", result.EABKID))
	}

	return &acme.EAB{
		KeyID:  result.EABKID,
		MACKey: result.EABHMACKey,
	}, acct, nil

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Reproduce the raw response: curl -fsSL -X POST https://app.zerossl.com/acme/eab-credentials-email -d 'email=you@example.com' and inspect what actually comes back.
  2. If a MITM proxy is in play, add an exception for app.zerossl.com or configure the host's trust store so the response passes through unmodified.
  3. Retry after a short wait — malformed bodies during ZeroSSL incidents are transient.
  4. Fall back to manual EAB credentials from the ZeroSSL dashboard.
Defensive patterns

Strategy: retry

Try / catch

if err := registerZeroSSL(ctx); err != nil {
    if strings.Contains(err.Error(), "decoding API response") {
        // malformed payload: usually transient (proxy/CDN glitch); retry with backoff
        time.Sleep(10 * time.Second)
        err = registerZeroSSL(ctx)
    }
}

Prevention

When it happens

Trigger: A transparent proxy or captive portal intercepting HTTPS and returning HTML; ZeroSSL returning a malformed/truncated response; a response body in an unexpected format from an API version change.

Common situations: Corporate MITM proxies rewriting responses; ZeroSSL API incidents; misconfigured local reverse proxies on the host; extremely rare in normal operation.

Related errors


AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15). Data as JSON: /api/errors/fed2ca5ac88ccade. Report an issue: GitHub.