juanfont/headscale · error · ErrInvalidHostIP
%w: hostname %q address %q
Error message
%w: hostname %q address %q
What it means
During Hosts.UnmarshalJSON, the host name passed Validate but its address value failed prefix.parseString, so it cannot be interpreted as an IP or CIDR prefix (ErrInvalidHostIP). Hostname and address are both included.
Source
Thrown at hscontrol/policy/v2/types.go:1426
if err != nil {
return err
}
*h = make(Hosts)
for key, value := range rawHosts {
host := Host(key)
err := host.Validate()
if err != nil {
return err
}
var prefix Prefix
err = prefix.parseString(value)
if err != nil {
return fmt.Errorf("%w: hostname %q address %q", ErrInvalidHostIP, key, value)
}
(*h)[host] = prefix
}
return nil
}
// MarshalJSON marshals the Hosts to JSON.
func (h *Hosts) MarshalJSON() ([]byte, error) {
if *h == nil {
return []byte("{}"), nil
}
rawHosts := make(map[string]string)
for host, prefix := range *h {
rawHosts[string(host)] = prefix.String()
}View on GitHub (pinned to 565fd254d0)
Solutions
- Set the value to a valid IP ("10.0.0.5") or CIDR prefix ("10.0.0.0/24")
- Use MagicDNS / node names instead of hosts if you wanted DNS-style aliasing
- Check for stray characters or missing netmask digits
Example fix
// before
"hosts": {"myserver": "myserver.example.com"}
// after
"hosts": {"myserver": "100.64.0.5"} Defensive patterns
Strategy: validation
Validate before calling
func validHostAddress(s string) bool {
if ip, err := netip.ParseAddr(s); err == nil { _ = ip; return true }
_, err := netip.ParsePrefix(s)
return err == nil
} Prevention
- hosts maps names to IPs/prefixes, not DNS names — use MagicDNS for name aliasing
- Validate addresses with netip.ParseAddr/ParsePrefix in policy generators
When it happens
Trigger: A hosts entry like "example-host": "not-an-ip", a bare word, or a malformed CIDR such as "10.0.0/24". DNS names are also rejected here: the value must be an address.
Common situations: Expecting hosts to alias DNS names instead of IPs; typos in octets or prefix lengths; using an IPv6 address with bad compression syntax.
Related errors
- host not defined in policy
- test destination must be a single host, not a CIDR range
- %w: %q
- %w %q
- test(s) failed
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/c8bf2d50160ec3a4.
Report an issue: GitHub.