{"record":{"id":"d5598423653bfdd3","repo":"MHSanaei/3x-ui","slug":"invalid-host-q","errorCode":null,"errorMessage":"invalid host %q","messagePattern":"invalid host %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/util/netsafe/netsafe.go","lineNumber":77,"sourceCode":"\t}\n\treturn nil, lastErr\n}\n\nvar hostnamePattern = regexp.MustCompile(`^[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(\\.[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?)*$`)\n\nfunc NormalizeHost(addr string) (string, error) {\n\taddr = strings.TrimSpace(addr)\n\tif addr == \"\" {\n\t\treturn \"\", fmt.Errorf(\"address is required\")\n\t}\n\tif strings.HasPrefix(addr, \"[\") && strings.HasSuffix(addr, \"]\") {\n\t\taddr = addr[1 : len(addr)-1]\n\t}\n\tif ip := net.ParseIP(addr); ip != nil {\n\t\treturn ip.String(), nil\n\t}\n\tif len(addr) > 253 || !hostnamePattern.MatchString(addr) {\n\t\treturn \"\", fmt.Errorf(\"invalid host %q\", addr)\n\t}\n\treturn addr, nil\n}\n","sourceCodeStart":59,"sourceCodeEnd":81,"githubUrl":"https://github.com/MHSanaei/3x-ui/blob/ad32144c42455696ea9f14e12168beac3e25f5d2/internal/util/netsafe/netsafe.go#L59-L81","documentation":"NormalizeHost accepts bracketed IPv6 literals, any parseable IP, or hostnames matching a strict LDH pattern (alphanumeric segments joined by dots, labels starting/ending alphanumeric, total length ≤ 253). Anything else — underscores, spaces, protocol prefixes, IPv6 without brackets, labels >63 chars — fails with 'invalid host %q'.","triggerScenarios":"Passing 'my_host.example.com' (underscore), 'example.com:443' (port included), 'fe80::1' without brackets, 'https://example.com' (full URL), a >253-char name, or a label with leading/trailing hyphen.","commonSituations":"Users pasting a full URL or host:port into an address-only field; Windows machine names with underscores; forgetting brackets on IPv6; DNS names with wildcard '*' segments; copy-paste adding an invisible space or trailing dot variants.","solutions":["Pass host only — strip scheme and port before calling (e.g. u.Hostname() output).","Replace underscores with hyphens in hostnames.","Wrap IPv6 literals in brackets: [fe80::1].","Shorten or fix >253-char or malformed labels; verify with `dig <host>` that the name is even legal."],"exampleFix":"// before\nhost, err := netsafe.NormalizeHost(\"https://example.com:443\") // invalid host\n\n// after\nu, _ := url.Parse(\"https://example.com:443\")\nhost, err := netsafe.NormalizeHost(u.Hostname()) // \"example.com\"","handlingStrategy":"type-guard","validationCode":"if _, err := netsafe.NormalizeHost(host); err != nil {\n    return fmt.Errorf(\"fix address field: %w\", err)\n}","typeGuard":"func isPlausibleHost(s string) bool {\n\ts = strings.TrimSpace(s)\n\tif strings.HasPrefix(s, \"[\") && strings.HasSuffix(s, \"]\") { return true }\n\tif net.ParseIP(s) != nil { return true }\n\treturn len(s) <= 253 && !strings.ContainsAny(s, \" :/@_\") && !strings.Contains(s, \"://\")\n}","tryCatchPattern":"host, err := netsafe.NormalizeHost(addr)\nif err != nil {\n    return fmt.Errorf(\"address %q must be a bare host or IP (no scheme/port): %w\", addr, err)\n}","preventionTips":["Store host and port in separate fields; never accept combined host:port in the address field.","Strip scheme/port with u.Hostname() before persisting user URLs.","Reject underscores and enforce bracketed IPv6 at input time."],"tags":["validation","hostname","url","configuration"],"backgroundTag":null,"analyzedSha":"ad32144c42455696ea9f14e12168beac3e25f5d2","analyzedAt":"2026-08-15T11:13:23.905Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}