{"record":{"id":"1c90db8fc96b251c","repo":"gofiber/fiber","slug":"domain-pattern-s-has-label-s-exceeding-rfc-1","errorCode":null,"errorMessage":"Domain pattern '%s' has label '%s' exceeding RFC 1035 limit of 63 characters (%d chars)","messagePattern":"Domain pattern '(.+?)' has label '(.+?)' exceeding RFC 1035 limit of 63 characters \\((.+?) chars\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"domain.go","lineNumber":112,"sourceCode":"\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\n\t\t\tm.parts[i] = part                              // keep \":param\" marker for matching\n\t\t} else {\n\t\t\t// Only lowercase constant labels (RFC 4343)\n\t\t\t// Enforce RFC 1035 per-label length limit (63 characters)\n\t\t\tif len(part) > 63 {\n\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' has label '%s' exceeding RFC 1035 limit of 63 characters (%d chars)\",\n\t\t\t\t\tpattern, part, len(part)))\n\t\t\t}\n\t\t\t// Validate label contains only valid ASCII domain characters (a-z, 0-9, hyphen).\n\t\t\tnormalized := utilsstrings.ToLower(part)\n\t\t\tfor _, ch := range normalized {\n\t\t\t\tif !isASCIIAlphanumeric(ch) && ch != '-' {\n\t\t\t\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' contains invalid character '%c' in label '%s'\", pattern, ch, part))\n\t\t\t\t}\n\t\t\t}\n\t\t\tm.parts[i] = normalized\n\t\t}\n\t}\n\n\t// Check if the domain pattern has too many parameters\n\tif len(m.paramNames) > maxParams {\n\t\tpanic(fmt.Sprintf(\"Domain pattern '%s' has %d parameters, which exceeds the maximum of %d\",\n\t\t\tpattern, len(m.paramNames), maxParams))\n\t}","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/domain.go#L94-L130","documentation":"A constant (non-parameter) label in a domain pattern is longer than 63 bytes, violating the RFC 1035 per-label length limit enforced by fiber's domainMatcher. DNS resolvers truncate or reject overlong labels, so the pattern is rejected at compile time. The check fires in the else-branch that handles literal labels (not ':param' segments).","triggerScenarios":"Passing a domain pattern containing one literal label longer than 63 characters, e.g. a generated/auto-named tenant slug, a long service name, or a pasted hash token used as a hostname label: app.Use(\"aaaaaaaaaaaaa...64chars....com\", handler).","commonSituations":"Programmatically building a domain pattern from a database column (tenant name, UUID, slug) without truncating; using a full URL or path segment as a label; copying a long subdomain from cloud infrastructure (AWS/GCP endpoints) into a route pattern.","solutions":["Shorten or truncate the offending label to <= 63 bytes.","If the long value is data (not a constant route), move it into a ':param' segment and match it at request time instead of baking it into the pattern.","Add a length assertion on each generated label before constructing the pattern string."],"exampleFix":"// before\nlabel := strings.Repeat(\"a\", 70)\napp.Use(label + \".example.com\", handler)\n// after\nif len(label) > 63 { label = label[:63] }\napp.Use(label + \".example.com\", handler)","handlingStrategy":"validation","validationCode":"// validateDomainLabels checks RFC 1035 per-label length (63) for constant labels.\nfunc validateDomainLabels(pattern string) error {\n    for _, lbl := range strings.Split(strings.TrimSuffix(pattern, \".\"), \".\") {\n        if strings.HasPrefix(lbl, \":\") {\n            continue // param label, length-checked by matcher differently\n        }\n        if len(lbl) > 63 {\n            return fmt.Errorf(\"label %q exceeds 63 bytes (%d)\", lbl, len(lbl))\n        }\n    }\n    return nil\n}\n\nif err := validateDomainLabels(domainPattern); err != nil { return err }","typeGuard":null,"tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        log.Fatalf(\"domain pattern invalid: %v\", r)\n    }\n}()\napp.Use(domainPattern, handler)","preventionTips":["Truncate or hash long data-derived labels before baking them into a pattern.","Prefer ':param' segments over giant literal labels for variable data.","Assert label length in any pattern-generation helper."],"tags":["routing","domain","dns","validation","startup"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}