juanfont/headscale · error
parsing IP address from database: %w
Error message
parsing IP address from database: %w
What it means
Each stored node address string from the ipv4/ipv6 columns is parsed with netip.ParseAddr; failure means a stored value is not a valid IP literal. This is a data-corruption error: headscale itself only ever writes parseable addresses, so a bad value implies external modification or a damaged database.
Source
Thrown at hscontrol/db/ip.go:119
// the database into account to start at a more "educated" location.
ret.prev4 = network4
}
if prefix6 != nil {
network6, broadcast6 := util.GetIPPrefixEndpoints(*prefix6)
ips.Add(network6)
ips.Add(broadcast6)
ret.prev6 = network6
}
// 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, nilView on GitHub (pinned to 565fd254d0)
Solutions
- Find the offending rows: SELECT id, hostname, ipv4, ipv6 FROM nodes WHERE ipv4 IS NOT NULL AND ipv4 != '' (inspect values manually).
- Correct or NULL out the malformed address and restart headscale.
- Never edit node IPs by hand — delete/re-register the node or use the API instead.
Example fix
-- before (corrupt row) UPDATE nodes SET ipv4 = '10.0.0.300' WHERE id = 7; -- invalid literal -- after UPDATE nodes SET ipv4 = '10.0.0.7' WHERE id = 7; -- or remove and re-register the node
Defensive patterns
Strategy: validation
Validate before calling
// Audit stored addresses before allocator construction:
// SELECT id, ipv4, ipv6 FROM nodes
// WHERE (ipv4 IS NOT NULL AND ipv4 != '' AND ipv4 NOT GLOB '*.*.*')
// OR (ipv6 IS NOT NULL AND ipv6 = '');
-- Or in Go over the plucked values:
func allParseable(vals []sql.NullString) bool {
for _, v := range vals {
if v.Valid && v.String != "" {
if _, err := netip.ParseAddr(v.String); err != nil { return false }
}
}
return true
} Try / catch
// Not retryable — repair data. Locate the malformed row via the audit // query, fix or NULL it, then restart. Escalate if rows were written by // headscale itself (that would be a bug worth reporting upstream).
Prevention
- Never hand-write node IP columns with SQL.
- Manage node lifecycle through the headscale CLI/API only.
- Validate third-party imports that touch the nodes table.
When it happens
Trigger: Someone hand-edited nodes.ipv4/ipv6 (e.g. set it to '10.0.0.256', an empty-but-non-null string, or a hostname); a buggy older version or external script wrote malformed values.
Common situations: Manual 'fixes' via SQL UPDATE on the nodes table; imports from third-party tooling; encoding corruption in a restored backup.
Related errors
- reading IPv4 addresses from database: %w
- reading IPv6 addresses from database: %w
- backfilling IPs: %w
- allocating IPv4 for node(%d): %w
- allocating IPv6 for node(%d): %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/0aa7905b40504b58.
Report an issue: GitHub.