{"record":{"id":"0e343dbafa67b155","repo":"coredns/coredns","slug":"invalid-acme-domain-q-w","errorCode":null,"errorMessage":"invalid ACME domain %q: %w","messagePattern":"invalid ACME domain %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/tls/acme.go","lineNumber":87,"sourceCode":"\t\troot = \".\"\n\t}\n\tstorage, err := filepath.Abs(filepath.Join(root, \".coredns\", \"acme\"))\n\tif err != nil {\n\t\treturn acmeOptions{}, fmt.Errorf(\"resolving ACME storage directory: %w\", err)\n\t}\n\treturn acmeOptions{ca: certmagic.DefaultACME.CA, storage: storage}, nil\n}\n\nfunc normalizeACMEDomain(domain string) (string, error) {\n\tdomain = strings.ToLower(strings.TrimSuffix(domain, \".\"))\n\twildcard := strings.HasPrefix(domain, \"*.\")\n\tcheck := strings.TrimPrefix(domain, \"*.\")\n\tif domain == \"\" || check == \"\" || strings.Contains(check, \"*\") || net.ParseIP(check) != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid ACME domain %q\", domain)\n\t}\n\tcheck, err := idna.Lookup.ToASCII(check)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"invalid ACME domain %q: %w\", domain, err)\n\t}\n\tif _, ok := dns.IsDomainName(check); !ok {\n\t\treturn \"\", fmt.Errorf(\"invalid ACME domain %q\", domain)\n\t}\n\tif wildcard {\n\t\treturn \"*.\" + check, nil\n\t}\n\treturn check, nil\n}\n\nfunc validateACMEOptions(o *acmeOptions) error {\n\tif len(o.domains) == 0 {\n\t\treturn errors.New(\"ACME requires at least one domain\")\n\t}\n\n\tseen := make(map[string]struct{}, len(o.domains))\n\tdomains := o.domains[:0]\n\tfor _, domain := range o.domains {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/coredns/coredns/blob/558c9757a92b361e550bdba82d0b4ddf3d12d595/plugin/tls/acme.go#L69-L105","documentation":"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.","triggerScenarios":"normalizeACMEDomain receives a domain whose IDNA conversion fails, e.g. malformed Unicode labels, invalid punycode, or disallowed characters per IDNA2008 rules.","commonSituations":"Copy-pasted internationalized domain containing disallowed characters or a bad \"xn--\" punycode label; encoding corruption in the Corefile (wrong charset).","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"],"exampleFix":"// before (invalid punycode)\ntls acme xn--example-.org\n// after (valid IDNA)\ntls acme Bücherei.example.org  // or xn--bcherei-k9a.example.org","handlingStrategy":"validation","validationCode":"if _, err := idna.Lookup.ToASCII(domain); err != nil {\n\t// invalid IDNA name — fix before putting in Corefile\n\treturn err\n}","typeGuard":null,"tryCatchPattern":"normalized, err := normalizeACMEDomain(d)\nif err != nil {\n\tif strings.Contains(err.Error(), \"idna\") || errors.Unwrap(err) != nil {\n\t\tlog.Printf(\"IDNA conversion failed for %q: %v\", d, err)\n\t}\n}","preventionTips":["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"],"tags":["tls","acme","idna","domain"],"backgroundTag":"invalid-identifier-format","analyzedSha":"558c9757a92b361e550bdba82d0b4ddf3d12d595","analyzedAt":"2026-09-06T22:47:02.106Z","contentChangedAt":"2026-09-06T22:47:02.106Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}