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

  1. Same remediation as 411: align schema and binary versions, verify connectivity.
  2. If 411 succeeded but 412 failed, suspect a transient — one restart usually resolves it.
  3. 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

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


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