{"id":"bab742972b8dd379","repo":"gofiber/fiber","slug":"domain-pattern-cannot-be-empty","errorCode":null,"errorMessage":"Domain pattern cannot be empty","messagePattern":"Domain pattern cannot be empty","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"domain.go","lineNumber":63,"sourceCode":"// maxDomainParts defines the maximum number of domain labels allowed (e.g., sub.domain.example.com = 4 parts).\n// This prevents DoS attacks from patterns or hostnames with excessive label counts.\n// RFC 1035 suggests 127 labels max, but we use a more conservative limit to prevent memory exhaustion.\nconst maxDomainParts = 16\n\n// parseDomainPattern parses a domain pattern like \":subdomain.example.com\"\n// into a domainMatcher. Parameter parts start with \":\".\n// Constant labels are lowercased per RFC 4343 (domain names are case-insensitive),\n// but parameter names are preserved as-is so that DomainParam lookups work with\n// the exact names the caller used (e.g., \":User\" → param name \"User\").\nfunc parseDomainPattern(pattern string) domainMatcher {\n\tpattern = utils.TrimSpace(pattern)\n\t// Trim trailing dot of a fully-qualified domain name (RFC 3986),\n\t// consistent with Fiber's own host normalization in Subdomains().\n\tpattern = utils.TrimRight(pattern, '.')\n\n\t// Validate pattern is not empty after trimming\n\tif pattern == \"\" {\n\t\tpanic(\"Domain pattern cannot be empty\")\n\t}\n\n\t// Enforce RFC 1035 total length limit on patterns\n\tif len(pattern) > 253 {\n\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' exceeds RFC 1035 maximum of 253 characters (%d chars)\",\n\t\t\tpattern, len(pattern)))\n\t}\n\n\tparts := strings.Split(pattern, \".\")\n\n\t// Prevent DoS from patterns with excessive label counts\n\tif len(parts) > maxDomainParts {\n\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' has %d parts, which exceeds the maximum of %d\",\n\t\t\tpattern, len(parts), maxDomainParts))\n\t}\n\n\tm := domainMatcher{\n\t\tparts:    make([]string, len(parts)),","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/domain.go#L45-L81","documentation":"Panics from domain.go:63 inside parseDomainPattern when the domain pattern is empty after TrimSpace and trimming trailing dots. Domain patterns drive host-based routing via app.Domain(pattern) / group.Domain(pattern); an empty pattern would match every host and shadow all other routes, so it is rejected.","triggerScenarios":"app.Domain(\"\") , app.Domain(\"   \"), app.Domain(\"...\") (all dots trimmed away), or app.Domain(strings.TrimSuffix(host, host)) that yields empty.","commonSituations":"Reading the domain from an env var that is unset; config-driven multi-tenant host patterns where a tenant has no domain configured; a default/empty string slipping through validation upstream.","solutions":["Provide a concrete non-empty domain pattern such as app.Domain(\"api.example.com\").","Validate the pattern is non-empty before calling Domain(); skip domain-scoped routes when unset.","Default the env var to a real hostname at config load time."],"exampleFix":"// before\nhost := os.Getenv(\"TENANT_HOST\") // \"\"\napp.Domain(host).Get(\"/\", h)\n\n// after\nhost := os.Getenv(\"TENANT_HOST\")\nif strings.TrimSpace(host) != \"\" {\n    app.Domain(host).Get(\"/\", h)\n} else {\n    app.Get(\"/\", h) // fallback, non-domain-scoped\n}","handlingStrategy":"validation","validationCode":"host := strings.TrimSpace(os.Getenv(\"TENANT_HOST\"))\nhost = strings.TrimRight(host, \".\")\nif host == \"\" {\n    return fmt.Errorf(\"TENANT_HOST must be set to a non-empty domain\")\n}\napp.Domain(host).Get(\"/\", h)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate domain patterns are non-empty before calling Domain().","Default env-driven host config to a real hostname.","Centralize domain-pattern construction in one helper that pre-validates."],"tags":["routing","domain","validation","panic","host-routing"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}