gofiber/fiber · error
Domain pattern ' ' contains invalid character '%c' in label
Error message
Domain pattern '%s' contains invalid character '%c' in label '%s'
What it means
A constant label in a domain pattern contains a character that is not a lowercase letter, digit, or hyphen after lowercasing (RFC 4343 lowercasing is applied first). Underscores, dots, spaces, punctuation, and non-ASCII characters are rejected because they are invalid in DNS hostnames. Note this applies to constant labels only — ':param' names additionally permit '_'.
Solutions
- Remove underscores and other punctuation from constant labels; use hyphens instead (e.g. 'foo-bar' not 'foo_bar').
- Punycode-encode any internationalized label (xn--...) before putting it in the pattern.
- If the underscore is intentional (e.g. _acme-challenge), route it as a ':param' segment or handle it outside the domain matcher.
Example fix
// before
app.Use("my_api.example.com", handler)
// after
app.Use("my-api.example.com", handler) Defensive patterns
Strategy: validation
Validate before calling
// validConstantLabel reports whether a literal label is DNS-safe (a-z0-9-).
func validConstantLabel(lbl string) bool {
if lbl == "" || len(lbl) > 63 {
return false
}
for _, ch := range strings.ToLower(lbl) {
if !((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-') {
return false
}
}
return true
}
for _, lbl := range strings.Split(domainPattern, ".") {
if strings.HasPrefix(lbl, ":") {
continue
}
if !validConstantLabel(lbl) {
return fmt.Errorf("invalid constant label %q", lbl)
}
} Try / catch
defer func() {
if r := recover(); r != nil {
log.Fatalf("invalid domain label: %v", r)
}
}()
app.Use(domainPattern, handler) Prevention
- Use hyphens, not underscores, in constant labels.
- Punycode-encode internationalized labels (golang.org/x/net/idna).
- Keep a linter/test that rejects '_' in any non-':param' label.
When it happens
Trigger: Passing a domain pattern whose literal labels contain '_', '.', ' ', ':', '@', or non-ASCII characters, e.g. app.Use("foo_bar.example.com", ...), app.Use("café.example.com", ...), app.Use("foo!bar.com", ...). The underscore in particular is allowed in param names but NOT in constant labels.
Common situations: Using snake_case hostnames (common in internal tooling/SRV records) as constant labels; pasting internationalized domain names without IDNA/punycode encoding; copy-paste introducing a trailing space or hidden unicode character; confusing param-name rules (which allow '_') with constant-label rules (which do not).
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Domain pattern ' ' has label ' ' exceeding RFC 1035 limit…
- Domain pattern cannot be empty
- Domain pattern ' ' contains empty label at position
- Domain pattern ' ' contains empty parameter name at position
- Domain pattern ' ' contains invalid parameter name ' ' with…
AI-assisted analysis of gofiber/fiber@a105acad6c (2026-08-11).
Data as JSON: /api/errors/a4bbfe77b1664a2e.
Report an issue: GitHub.
Appendix: source
Thrown at domain.go:119
if !isASCIIAlphanumeric(ch) && ch != '_' && ch != '-' {
panic(fmt.Sprintf("Domain pattern '%s' contains invalid parameter name '%s' with character '%c'", pattern, paramName, ch))
}
}
m.paramIdx = append(m.paramIdx, i)
m.paramNames = append(m.paramNames, paramName) // preserve original case
m.parts[i] = part // keep ":param" marker for matching
} else {
// Only lowercase constant labels (RFC 4343)
// Enforce RFC 1035 per-label length limit (63 characters)
if len(part) > 63 {
panic(fmt.Sprintf("Domain pattern '%s' has label '%s' exceeding RFC 1035 limit of 63 characters (%d chars)",
pattern, part, len(part)))
}
// Validate label contains only valid ASCII domain characters (a-z, 0-9, hyphen).
normalized := utilsstrings.ToLower(part)
for _, ch := range normalized {
if !isASCIIAlphanumeric(ch) && ch != '-' {
panic(fmt.Sprintf("Domain pattern '%s' contains invalid character '%c' in label '%s'", pattern, ch, part))
}
}
m.parts[i] = normalized
}
}
// Check if the domain pattern has too many parameters
if len(m.paramNames) > maxParams {
panic(fmt.Sprintf("Domain pattern '%s' has %d parameters, which exceeds the maximum of %d",
pattern, len(m.paramNames), maxParams))
}
return m
}
// match checks if a hostname matches the domain pattern.
// It returns true if matched and a slice of parameter values (parallel to paramNames).
// Uses a stack-allocated buffer to avoid heap allocation for typical domain names.View on GitHub (pinned to a105acad6c)