juanfont/headscale · error
reading IPv6 addresses from database: %w
Error message
reading IPv6 addresses from database: %w
What it means
Companion to error 411: the allocator plucks the ipv6 column of all nodes to seed the used-IP set. Fails for the same classes of reason — broken connection, missing ipv6 column, or a blocked read — just on the second query.
Source
Thrown at hscontrol/db/ip.go:86
var (
v4s []sql.NullString
v6s []sql.NullString
)
if db != nil {
err := db.Read(func(rx *gorm.DB) error {
return rx.Model(&types.Node{}).Pluck("ipv4", &v4s).Error
})
if err != nil {
return nil, fmt.Errorf("reading IPv4 addresses from database: %w", err)
}
err = db.Read(func(rx *gorm.DB) error {
return rx.Model(&types.Node{}).Pluck("ipv6", &v6s).Error
})
if err != nil {
return nil, fmt.Errorf("reading IPv6 addresses from database: %w", err)
}
}
var ips netipx.IPSetBuilder
// Add network and broadcast addrs to used pool so they
// are not handed out to nodes.
if prefix4 != nil {
network4, broadcast4 := util.GetIPPrefixEndpoints(*prefix4)
ips.Add(network4)
ips.Add(broadcast4)
// Use network as starting point, it will be used to call .Next()
// TODO(kradalby): Could potentially take all the IPs loaded from
// the database into account to start at a more "educated" location.
ret.prev4 = network4
}
View on GitHub (pinned to 565fd254d0)
Solutions
- Same remediation as 411: align schema and binary versions, verify connectivity.
- If 411 succeeded but 412 failed, suspect a transient — one restart usually resolves it.
- Confirm prefixes (ip_prefixes) config includes valid v4/v6 entries so the allocator is built against a sane config.
Defensive patterns
Strategy: try-catch
Try / catch
// Mirror of 411: catch, inspect chained driver error, distinguish // 'column doesn't exist' (run migrations) from transient connection loss // (retry once after re-dial).
Prevention
- Ensure schema and binary versions match before startup.
- Use connection pooling with health checks for postgres.
When it happens
Trigger: Identical to 411 but affecting the ipv6 pluck: schema without nodes.ipv6, connection drop between the two queries, sqlite busy timeout.
Common situations: Same as 411; seeing 412 but not 411 suggests a transient failure between the two reads rather than schema drift.
Related errors
- reading IPv4 addresses from database: %w
- allocating IPv6 for node(%d): %w
- database type not supported
- no IPv4 or IPv6 prefix configured, minimum one prefix is req
- init state: %w
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/cfd6d0f5519482cf.
Report an issue: GitHub.