juanfont/headscale · error
ErrHostnameTooLong
ErrHostnameTooLong
Error message
creating valid FQDN (%s): %w
What it means
Returned by Node.GetFQDN when combining the node's GivenName with base_domain (plus trailing dot) exceeds MaxHostnameLength (255 ASCII chars). It wraps ErrHostnameTooLong. The mapper needs a valid FQDN to build the MapResponse, so an over-long name is a hard failure, not a truncation.
Source
Thrown at hscontrol/types/node.go:511
}
func (node *Node) GetFQDN(baseDomain string) (string, error) {
if node.GivenName == "" {
return "", fmt.Errorf("creating valid FQDN: %w", ErrNodeHasNoGivenName)
}
hostname := node.GivenName
if baseDomain != "" {
hostname = fmt.Sprintf(
"%s.%s.",
node.GivenName,
baseDomain,
)
}
if len(hostname) > MaxHostnameLength {
return "", fmt.Errorf(
"creating valid FQDN (%s): %w",
hostname,
ErrHostnameTooLong,
)
}
return hostname, nil
}
// ValidateGivenName reports whether givenName is usable as a node's DNS label:
// a valid DNS label that, combined with baseDomain, yields an FQDN within
// MaxHostnameLength. Admin-facing write paths (e.g. node rename) reject names
// that fail this, since the mapper cannot build a map for a node — or any of
// its peers — whose GetFQDN fails. Derived paths sanitise/coerce instead.
func ValidateGivenName(givenName, baseDomain string) error {
err := dnsname.ValidLabel(givenName)
if err != nil {
return fmt.Errorf("%q is not a valid DNS label: %w", givenName, err)View on GitHub (pinned to 565fd254d0)
Solutions
- Shorten the node's given name (hostname) before registering or renaming it
- Shorten dns.base_domain in the headscale config
- Validate prospective names with types.ValidateGivenName before applying them in admin tooling
Example fix
// before
baseDomain := "very-long-example-subdomain.tailnet.example-corporation.internal."
node := &Node{GivenName: "machine-with-a-very-long-hostname"}
fqdn, err := node.GetFQDN(baseDomain) // ErrHostnameTooLong
// after
baseDomain := "tailnet.example.com"
node := &Node{GivenName: "build01"}
fqdn, err := node.GetFQDN(baseDomain) Defensive patterns
Strategy: validation
Validate before calling
import "headscale/hscontrol/types"
// call before renaming or pre-registering a node
if err := types.ValidateGivenName(newName, cfg.TailcfgDNS.BaseDomain); err != nil {
return err // includes hostname-too-long via GetFQDN reuse
} Try / catch
fqdn, err := node.GetFQDN(baseDomain)
if err != nil {
if errors.Is(err, types.ErrHostnameTooLong) {
// shorten name or base domain, then retry
}
return err
} Prevention
- Keep given names short (machine role + number) regardless of the 63-char label cap
- Prefer a short dns.base_domain so headroom exists for long hostnames
- Validate names with ValidateGivenName in admin tooling before they reach the mapper
When it happens
Trigger: A node registers (or is renamed to) a long GivenName while dns.base_domain is long enough that given + '.' + base + '.' exceeds 255 characters. GetFQDN(baseDomain) is called from the mapper and from ValidateGivenName.
Common situations: Machines with long hostnames joining a tailnet with a long MagicDNS base_domain; admin rename operations that pass a very long name; DNS label is valid (≤63 chars) but the FQDN overflows under the base domain.
Related errors
- %q is not a valid DNS label: %w
- node name is not unique
- hostname contains invalid IP address
- given name already in use by another node
- server_url cannot be part of base_domain in a way that could
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/3c752738f2ce0017.
Report an issue: GitHub.