juanfont/headscale · error

registering existing node in database: %w

Error message

registering existing node in database: %w

What it means

When a node re-registers and already holds at least one IP, RegisterNode takes the fast path of saving the refreshed node (expiry, node key from the registration cache). This error is that tx.Save failing — typically a unique-constraint hit on machine key/node key or a database availability problem.

Source

Thrown at hscontrol/db/node.go:310

		node.GivenName = oldNode.GivenName
		node.ApprovedRoutes = oldNode.ApprovedRoutes
		// Don't overwrite the provided IPs with old ones when they exist
		if ipv4 == nil {
			ipv4 = oldNode.IPv4
		}

		if ipv6 == nil {
			ipv6 = oldNode.IPv6
		}
	}

	// If the node exists and it already has IP(s), we just save it
	// so we store the node.Expire and node.Nodekey that has been set when
	// adding it to the registrationCache
	if node.IPv4 != nil || node.IPv6 != nil {
		err := tx.Save(&node).Error
		if err != nil {
			return nil, fmt.Errorf("registering existing node in database: %w", err)
		}

		log.Trace().
			Caller().
			Str(zf.NodeHostname, node.Hostname).
			Str(zf.MachineKey, node.MachineKey.ShortString()).
			Str(zf.NodeKey, node.NodeKey.ShortString()).
			Str(zf.UserName, node.User.Username()).
			Msg("Test node authorized again")

		return &node, nil
	}

	node.IPv4 = ipv4
	node.IPv6 = ipv6

	if node.GivenName == "" {
		node.GivenName = dnsname.SanitizeHostname(node.Hostname)

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Unwrap the error; unique violations point to concurrent registration — serialize per machine key
  2. For lock/connectivity causes, address SQLite contention or Postgres health and let the client retry registration
  3. Inspect the nodes table for conflicting machine_key/node_key rows
Defensive patterns

Strategy: try-catch

Try / catch

node, err := db.RegisterNode(tx, node)
if err != nil {
	if isUniqueViolation(err) {
		// concurrent registration of same machine; reload and take existing path
	}
	return nil, err
}

Prevention

When it happens

Trigger: Concurrent re-registration of the same machine from two clients; node key colliding with another row after key rotation; DB lock or connection loss during registration.

Common situations: Client retry during network flakiness causing parallel registration attempts; clock skew or restored DB producing key conflicts.

Related errors


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