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

  1. Shorten the node's given name (hostname) before registering or renaming it
  2. Shorten dns.base_domain in the headscale config
  3. 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

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


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/3c752738f2ce0017. Report an issue: GitHub.