juanfont/headscale · error

building initial IP Set: %w

Error message

building initial IP Set: %w

What it means

After adding all reserved and used addresses to a netipx.IPSetBuilder, the constructor calls IPSet() once to validate. Failure means the accumulated set is internally inconsistent — practically, that configured prefixes contain invalid or contradictory addresses (e.g. a misparsed ip_prefixes entry producing a bad reserved address).

Source

Thrown at hscontrol/db/ip.go:129

	}

	// Fetch all the IP Addresses currently handed out from the Database
	// and add them to the used IP set.
	for _, addrStr := range append(v4s, v6s...) {
		if addrStr.Valid {
			addr, err := netip.ParseAddr(addrStr.String)
			if err != nil {
				return nil, fmt.Errorf("parsing IP address from database: %w", err)
			}

			ips.Add(addr)
		}
	}

	// Build the initial IPSet to validate that we can use it.
	_, err := ips.IPSet()
	if err != nil {
		return nil, fmt.Errorf(
			"building initial IP Set: %w",
			err,
		)
	}

	ret.usedIPs = ips

	return &ret, nil
}

func (i *IPAllocator) Next() (*netip.Addr, *netip.Addr, error) {
	var (
		err  error
		ret4 *netip.Addr
		ret6 *netip.Addr
	)

	if i.prefix4 != nil {

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Validate every entry in ip_prefixes is a well-formed CIDR of the intended family.
  2. Reset to the defaults (100.64.0.0/10 and fd7a:115c:a1e0::/48) and confirm startup, then re-apply custom prefixes one by one.
  3. Ensure prefixes do not overlap each other.

Example fix

# before (config.yaml)
ip_prefixes:
  - 100.64.0.0/10
  - fd7a:115c:a1e0::49 # typo, not a /48 prefix

# after
ip_prefixes:
  - 100.64.0.0/10
  - fd7a:115c:a1e0::/48
Defensive patterns

Strategy: validation

Validate before calling

import "net/netip"

func validatePrefixes(raw []string) error {
    for _, s := range raw {
        p, err := netip.ParsePrefix(strings.TrimSpace(s))
        if err != nil {
            return fmt.Errorf("invalid prefix %q: %w", s, err)
        }
        if p != p.Masked() {
            return fmt.Errorf("prefix %q has host bits set", s)
        }
    }
    return nil
}

Try / catch

// Config-level failure with no runtime recovery: fix ip_prefixes and
// restart. Validate prefixes in a config linter before deploy.

Prevention

When it happens

Trigger: ip_prefixes config containing a value that netipx cannot reconcile into a ranged set — invalid CIDR, mixed-family bytes fed into the builder, or a zero-value prefix producing an invalid endpoint via GetIPPrefixEndpoints.

Common situations: Hand-edited ip_prefixes with a typo ('100.64.0.0/10 ' with space, 'fd7a:115c:a1e0::/48' mistyped); config migrated from an old format; environment variable override mistakes.

Related errors


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