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
- Verify the configured email is a real, correctly formatted mailbox you control (it receives ZeroSSL notifications).
- Match the error code against ZeroSSL's API documentation (e.g. code 202 = invalid email) and correct the input.
- If rate limited, wait before retrying or use manual EAB credentials generated in the ZeroSSL dashboard under Developer settings.
- 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
- Use a real mailbox for the email option; avoid test@example-style addresses.
- Cross-reference the reported ZeroSSL error code in the message with their API docs.
- Keep manual EAB credentials as a fallback for rejected emails.
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
- your email address is required to use ZeroSSL's ACME endpoin
- expanding email address '%s': %v
- DNS challenge enabled, but no DNS provider configured
- forming request: %v
- performing EAB credentials request: %v
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/65807af788631e36.
Report an issue: GitHub.