{"record":{"id":"1cf2e60ee126e7fd","repo":"juanfont/headscale","slug":"q-is-not-a-valid-dns-label-w","errorCode":null,"errorMessage":"%q is not a valid DNS label: %w","messagePattern":"%q is not a valid DNS label: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hscontrol/types/node.go","lineNumber":529,"sourceCode":"\t\treturn \"\", fmt.Errorf(\n\t\t\t\"creating valid FQDN (%s): %w\",\n\t\t\thostname,\n\t\t\tErrHostnameTooLong,\n\t\t)\n\t}\n\n\treturn hostname, nil\n}\n\n// ValidateGivenName reports whether givenName is usable as a node's DNS label:\n// a valid DNS label that, combined with baseDomain, yields an FQDN within\n// MaxHostnameLength. Admin-facing write paths (e.g. node rename) reject names\n// that fail this, since the mapper cannot build a map for a node — or any of\n// its peers — whose GetFQDN fails. Derived paths sanitise/coerce instead.\nfunc ValidateGivenName(givenName, baseDomain string) error {\n\terr := dnsname.ValidLabel(givenName)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%q is not a valid DNS label: %w\", givenName, err)\n\t}\n\n\t// Reuse GetFQDN so the length bound stays identical to what the mapper\n\t// enforces; a valid 63-char label can still overflow under a long\n\t// base_domain.\n\t_, err = (&Node{GivenName: givenName}).GetFQDN(baseDomain)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// AnnouncedRoutes returns the list of routes the node announces, as\n// reported by the client in [tailcfg.Hostinfo.RoutableIPs]. Announcement alone\n// does not grant visibility — see [Node.SubnetRoutes] for approval-gated\n// access.\nfunc (node *Node) AnnouncedRoutes() []netip.Prefix {","sourceCodeStart":511,"sourceCodeEnd":547,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/types/node.go#L511-L547","documentation":"Returned by types.ValidateGivenName when the candidate name fails dnsname.ValidLabel — i.e. it is not a legal DNS label (empty, >63 chars, illegal characters, leading/trailing hyphen). Admin write paths such as node rename call this first because the mapper cannot build a map for a node whose FQDN cannot be formed.","triggerScenarios":"Calling ValidateGivenName with names like \"my machine\" (space), \"-lead\", \"trail-\", \"a\"*64, \"under_score\", or \"\" — used in rename handlers and provisioning code before persisting a GivenName.","commonSituations":"Users renaming nodes via the CLI/API with hostnames containing spaces, underscores, or other non-DNS characters; automation scripts deriving node names from free-text asset labels.","solutions":["Use a strict DNS label: 1-63 chars, letters/digits/hyphens only, no leading or trailing hyphen","Sanitize free-text names before rename: lowercase, replace separators with hyphens, trim hyphens, cap at 63 chars","Run ValidateGivenName in your tooling before submitting the rename so the error surfaces early with context"],"exampleFix":"// before\nname := \"file server (2)\"\nerr := types.ValidateGivenName(name, baseDomain) // not a valid DNS label\n// after\nname := \"file-server-2\"\nerr := types.ValidateGivenName(name, baseDomain)","handlingStrategy":"validation","validationCode":"import (\n    \"regexp\"\n    \"headscale/hscontrol/types\"\n)\n\nvar dnsLabel = regexp.MustCompile(`^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$`)\n\nfunc safeGivenName(raw string) (string, error) {\n    if !dnsLabel.MatchString(raw) {\n        return \"\", fmt.Errorf(\"%q is not DNS-label safe\", raw)\n    }\n    if err := types.ValidateGivenName(raw, baseDomain); err != nil {\n        return \"\", err\n    }\n    return raw, nil\n}","typeGuard":null,"tryCatchPattern":"if err := types.ValidateGivenName(name, baseDomain); err != nil {\n    // derive a sanitized fallback instead of persisting the bad name\n    name = sanitizeToDNSLabel(name)\n}","preventionTips":["Generate node names from an allowlist pattern (alnum + hyphen) in automation","Trim and lowercase user-supplied names before validation","Surface validation errors in rename UIs before submission"],"tags":["dns","validation","node","rename"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}