{"record":{"id":"fc980bccbcebcf02","repo":"gofiber/fiber","slug":"domain-pattern-s-has-d-parts-which-exceeds-th","errorCode":null,"errorMessage":"Domain pattern '%s' has %d parts, which exceeds the maximum of %d","messagePattern":"Domain pattern '(.+?)' has (.+?) parts, which exceeds the maximum of (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"domain.go","lineNumber":76,"sourceCode":"\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)),\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))","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/domain.go#L58-L94","documentation":"parseDomainPattern splits the pattern on '.' and rejects any pattern with more than maxDomainParts labels to prevent DoS via pathological patterns (each label is processed and matched per request). This is a defensive cap on pattern complexity.","triggerScenarios":"Passing a pattern like a.b.c.d....z with more labels than maxDomainParts allows; or a pattern constructed by joining many tokens without limit.","commonSituations":"Building a domain pattern from a list of user-supplied segments; copy-paste of a deep subdomain chain; misconfigured wildcard expansion.","solutions":["Reduce the number of dot-separated labels below maxDomainParts (check the constant in domain.go for the exact cap).","Validate segment count before registering: if len(strings.Split(p, \".\")) > cap { return error }.","Collapse redundant subdomains or use a wildcard parameter label."],"exampleFix":"// before\npattern := strings.Join(segments, \".\")  // segments has 200 entries\napp.Domain(pattern)\n\n// after\nif len(segments) > maxDomainParts { return fmt.Errorf(\"too many domain labels\") }\napp.Domain(strings.Join(segments, \".\"))","handlingStrategy":"validation","validationCode":"// Reject patterns with too many labels before registration\nfunc validateDomainParts(p string, max int) error {\n    n := strings.Count(p, \".\") + 1\n    if n > max { return fmt.Errorf(\"too many domain labels: %d > %d\", n, max) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Bound the number of segments when composing patterns from lists.","Document the maxDomainParts cap for your team.","Use wildcard parameter labels to absorb redundant subdomains."],"tags":["routing","domain","validation","dos-prevention","startup"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}