caddyserver/caddy · error

failed getting EAB credentials: HTTP %d: %s (code %d)

Error message

failed getting EAB credentials: HTTP %d: %s (code %d)

What it means

ZeroSSL's EAB API responded with a structured error: the decoded JSON contains a non-zero error.code, and Caddy reports the HTTP status, error type, and API error code. Notably ZeroSSL returns HTTP 200 even on errors, so this code field is checked before the status code. Typical codes include invalid email (202) or hitting API limits.

Source

Thrown at modules/caddytls/acmeissuer.go:406

	}
	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
}

// UnmarshalCaddyfile deserializes Caddyfile tokens into iss.
//

View on GitHub (pinned to 50e54ee279)

Solutions

  1. Verify the configured email is a real, correctly formatted mailbox you control (it receives ZeroSSL notifications).
  2. Match the error code against ZeroSSL's API documentation (e.g. code 202 = invalid email) and correct the input.
  3. If rate limited, wait before retrying or use manual EAB credentials generated in the ZeroSSL dashboard under Developer settings.
  4. Ensure only one Caddy instance/key per policy is requesting EAB to avoid limit exhaustion.

Example fix

# before
{
	email not-an-email
}

# after
{
	email admin@example.com
}
Defensive patterns

Strategy: validation

Validate before calling

// RFC-ish email sanity check before relying on ZeroSSL auto-EAB.
func validEmail(s string) bool {
    at := strings.IndexByte(s, '@')
    return at > 0 && at < len(s)-1 && !strings.ContainsAny(s, " \\t")
}

Prevention

When it happens

Trigger: POSTing an invalid/malformed email to /acme/eab-credentials-email; ZeroSSL rejecting the account creation (e.g. blocked email domain); API rate limiting; ZeroSSL API reporting 'Email does not look right' style errors.

Common situations: Typo'd or syntactically invalid email in the global email option; disposable/placeholder emails like test@test.com being rejected; repeated issuance attempts from the same IP hitting ZeroSSL's limits.

Related errors


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