coredns/coredns · error
invalid ACME domain %q: %w
Error message
invalid ACME domain %q: %w
What it means
Validation error in the ACME helper normalizeACMEDomain. The domain is unusable for certificate issuance — it is empty, consists only of the wildcard prefix, contains an interior '*', or is an IP address (ACME cannot issue for IPs) — so the wrapped reason is reported to the caller.
Source
Thrown at plugin/tls/acme.go:87
root = "."
}
storage, err := filepath.Abs(filepath.Join(root, ".coredns", "acme"))
if err != nil {
return acmeOptions{}, fmt.Errorf("resolving ACME storage directory: %w", err)
}
return acmeOptions{ca: certmagic.DefaultACME.CA, storage: storage}, nil
}
func normalizeACMEDomain(domain string) (string, error) {
domain = strings.ToLower(strings.TrimSuffix(domain, "."))
wildcard := strings.HasPrefix(domain, "*.")
check := strings.TrimPrefix(domain, "*.")
if domain == "" || check == "" || strings.Contains(check, "*") || net.ParseIP(check) != nil {
return "", fmt.Errorf("invalid ACME domain %q", domain)
}
check, err := idna.Lookup.ToASCII(check)
if err != nil {
return "", fmt.Errorf("invalid ACME domain %q: %w", domain, err)
}
if _, ok := dns.IsDomainName(check); !ok {
return "", fmt.Errorf("invalid ACME domain %q", domain)
}
if wildcard {
return "*." + check, nil
}
return check, nil
}
func validateACMEOptions(o *acmeOptions) error {
if len(o.domains) == 0 {
return errors.New("ACME requires at least one domain")
}
seen := make(map[string]struct{}, len(o.domains))
domains := o.domains[:0]
for _, domain := range o.domains {View on GitHub (pinned to 558c9757a9)
Solutions
- Correct the internationalized domain name spelling in the Corefile
- Use valid punycode (xn--...) ASCII form directly
- Save the Corefile as UTF-8 and re-check for corrupted bytes
- Test the name with an IDNA library before deploying
Example fix
// before (invalid punycode) tls acme xn--example-.org // after (valid IDNA) tls acme Bücherei.example.org // or xn--bcherei-k9a.example.org
Defensive patterns
Strategy: validation
Validate before calling
if _, err := idna.Lookup.ToASCII(domain); err != nil {
// invalid IDNA name — fix before putting in Corefile
return err
} Try / catch
normalized, err := normalizeACMEDomain(d)
if err != nil {
if strings.Contains(err.Error(), "idna") || errors.Unwrap(err) != nil {
log.Printf("IDNA conversion failed for %q: %v", d, err)
}
} Prevention
- Encode internationalized names to punycode before adding them to the Corefile
- Save Corefiles as UTF-8
- Test unusual Unicode domains locally before deploying
- Avoid copy-pasting domains from sources that may include zero-width characters
When it happens
Trigger: normalizeACMEDomain receives a domain whose IDNA conversion fails, e.g. malformed Unicode labels, invalid punycode, or disallowed characters per IDNA2008 rules.
Common situations: Copy-pasted internationalized domain containing disallowed characters or a bad "xn--" punycode label; encoding corruption in the Corefile (wrong charset).
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- invalid ACME domain %q
- ACME certificate is not ready
- server name is not managed by this ACME configuration
- resolving ACME storage directory: %w
- invalid ACME CA URL %q
AI-assisted analysis of coredns/coredns@558c9757a9 (2026-09-06).
Data as JSON: /api/errors/0e343dbafa67b155.
Report an issue: GitHub.