caddyserver/caddy · error
converting hostname '%s' to ASCII: %v
Error message
converting hostname '%s' to ASCII: %v
What it means
MatchHost.Provision normalizes every `host` matcher entry with x/net/idna ToASCII before lowercasing and de-duplicating. If a host cannot be converted to punycode (malformed labels, bad characters, over-long labels), provisioning fails with this error naming the host.
Source
Thrown at modules/caddyhttp/matchers.go:263
// iterate to merge multiple matchers into one
for d.Next() {
*m = append(*m, d.RemainingArgs()...)
if d.NextBlock(0) {
return d.Err("malformed host matcher: blocks are not supported")
}
}
return nil
}
// Provision sets up and validates m, including making it more efficient for large lists.
func (m MatchHost) Provision(_ caddy.Context) error {
// check for duplicates; they are nonsensical and reduce efficiency
// (we could just remove them, but the user should know their config is erroneous)
seen := make(map[string]int, len(m))
for i, host := range m {
asciiHost, err := idna.ToASCII(host)
if err != nil {
return fmt.Errorf("converting hostname '%s' to ASCII: %v", host, err)
}
normalizedHost := strings.ToLower(asciiHost)
if firstI, ok := seen[normalizedHost]; ok {
return fmt.Errorf("host at index %d is repeated at index %d: %s", firstI, i, host)
}
// Normalize exact hosts for standardized comparison in large-list fastpath later on.
// Keep wildcards/placeholders untouched.
if m.fuzzy(asciiHost) {
m[i] = asciiHost
} else {
m[i] = normalizedHost
}
seen[normalizedHost] = i
}
if m.large() {
// sort the slice lexicographically, grouping "fuzzy" entries (wildcards and placeholders)
// at the front of the list; this allows us to use binary search for exact matches, whichView on GitHub (pinned to 50e54ee279)
Solutions
- Correct the hostname: no spaces, no empty labels, labels ≤63 chars, valid characters only.
- For internal names with underscores, test the exact entry against idna.ToASCII; if rejected, rename the service or match on a different field.
- Quote and lint host lists when generating config to catch stray characters.
Example fix
// before (Caddyfile) @ok host "exa mple.com" // after @ok host example.com
Defensive patterns
Strategy: validation
Validate before calling
import "golang.org/x/net/idna"
func validHostnames(hosts []string) bool {
for _, h := range hosts {
if _, err := idna.ToASCII(h); err != nil {
return false
}
}
return true
} Prevention
- No spaces or empty labels; labels ≤63 chars.
- Test underscore-bearing internal names with idna.ToASCII before shipping.
- Trim and lint host lists from certificates/SANs.
When it happens
Trigger: `host` matcher entries like "exa mple.com" (space), "-leadinghyphen.example.com", labels longer than 63 chars, empty labels ("a..com"), or characters the IDNA profile rejects such as underscores in strict profiles.
Common situations: Wildcard/certificate-san lists pasted with invisible whitespace; underscores in internal hostnames (some older Caddy versions tolerated `_` in host matchers, newer IDNA handling is stricter); U-labels with combining marks that fail validation.
Related errors
- host at index %d is repeated at index %d: %s
- --config is required
- the 'forwarded' option is no longer supported; use the 'clie
- unknown object ID '%s'
- decoding request body: %w, at offset %d
AI-assisted analysis of caddyserver/caddy@50e54ee279 (2026-08-15).
Data as JSON: /api/errors/1cd87cad2b04691f.
Report an issue: GitHub.