{"id":"6b4f3f00249a5121","repo":"gofiber/fiber","slug":"domain-pattern-s-contains-empty-label-at-positi","errorCode":null,"errorMessage":"Domain pattern '%s' contains empty label at position %d","messagePattern":"Domain pattern '(.+?)' contains empty label at position (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"domain.go","lineNumber":88,"sourceCode":"\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)),\n\t\tnumParts: len(parts),\n\t}\n\n\tfor i, part := range parts {\n\t\t// Validate no empty labels (e.g., \"example..com\" is invalid)\n\t\tif part == \"\" {\n\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains empty label at position %d\", pattern, i))\n\t\t}\n\n\t\tif part[0] == ':' {\n\t\t\t// Validate parameter name is not empty\n\t\t\tif len(part) == 1 {\n\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains empty parameter name at position %d\", pattern, i))\n\t\t\t}\n\t\t\tparamName := part[1:]\n\t\t\t// Validate parameter name contains only ASCII-safe characters (a-z, A-Z, 0-9, underscore, hyphen).\n\t\t\t// Using explicit ASCII ranges rather than unicode.IsLetter/IsDigit to reject non-ASCII\n\t\t\t// characters that are invalid in DNS names.\n\t\t\tfor _, ch := range paramName {\n\t\t\t\tif !isASCIIAlphanumeric(ch) && ch != '_' && ch != '-' {\n\t\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains invalid parameter name '%s' with character '%c'\", pattern, paramName, ch))\n\t\t\t\t}\n\t\t\t}\n\t\t\tm.paramIdx = append(m.paramIdx, i)\n\t\t\tm.paramNames = append(m.paramNames, paramName) // preserve original case","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/gofiber/fiber/blob/9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c/domain.go#L70-L106","documentation":"Panics from domain.go:88 when a dot-separated label is empty, i.e. consecutive dots in the pattern (\"example..com\"). Empty labels are invalid per RFC 1035 and would produce ambiguous matching, so parseDomainPattern rejects them per-label.","triggerScenarios":"app.Domain(\"example..com\"), app.Domain(\".example.com\") (leading dot yields empty first label after split), or app.Domain(\"example.com.\") is fine (trailing dot trimmed), but \"example..com.\" is not.","commonSituations":"Concatenating labels with a missing value: domain := part + \".\" + part2 where part2 is empty; trailing/leading dots from sloppy string formatting; config typos.","solutions":["Fix the pattern to have no empty labels: \"example.com\", \"sub.example.com\".","Sanitize the pattern by collapsing/stripping stray dots before calling Domain().","Build patterns from a slice of non-empty labels joined by \".\"."],"exampleFix":"// before\ndomain := tenant + \".\" + suffix // suffix == \"\" -> \"acme.\"\napp.Domain(domain).Get(\"/\", h)\n\n// after\nlabels := []string{tenant}\nif suffix != \"\" {\n    labels = append(labels, suffix)\n}\ndomain := strings.Join(labels, \".\") // \"acme\"\napp.Domain(domain).Get(\"/\", h)","handlingStrategy":"validation","validationCode":"for _, label := range strings.Split(pattern, \".\") {\n    if label == \"\" {\n        return fmt.Errorf(\"domain pattern has empty label\")\n    }\n}\napp.Domain(pattern).Get(\"/\", h)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build patterns by joining a slice of non-empty labels with \".\".","Sanitize stray leading/trailing/double dots before registering.","Unit-test pattern construction with empty inputs."],"tags":["routing","domain","validation","rfc-1035","panic"],"analyzedSha":"9a4c7e57fe0b080a04235d28a4b0d2b4b353d58c","analyzedAt":"2026-08-04T21:44:03.395Z","schemaVersion":2}