juanfont/headscale · error

updating policy manager nodes: %w

Error message

updating policy manager nodes: %w

What it means

Same auth-callback tail as the users update, but for the node set: updatePolicyManagerNodes() failed after the node was registered, the cache entry finished, and the users update succeeded. The node exists in NodeStore and DB; only the policy manager's view of nodes is stale until the next successful policy update.

Source

Thrown at hscontrol/state/state.go:2351

			return types.NodeView{}, change.Change{}, err
		}
	}

	// Signal to waiting clients
	regEntry.FinishAuth(types.AuthVerdict{Node: finalNode})

	// Remove from registration cache
	s.authCache.Remove(authID)

	// Update policy managers
	usersChange, err := s.updatePolicyManagerUsers()
	if err != nil {
		return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("updating policy manager users: %w", err)
	}

	nodesChange, err := s.updatePolicyManagerNodes()
	if err != nil {
		return finalNode, change.NodeAdded(finalNode.ID()), fmt.Errorf("updating policy manager nodes: %w", err)
	}

	policyChanged := !usersChange.IsEmpty() || !nodesChange.IsEmpty()

	// nodeExistsForSameUser is true only for a same-user relogin; a tag->user
	// conversion is excluded, as it changes the peer's User — a structural
	// change peers must see in full, not a key-rotation patch.
	return finalNode, reauthChange(finalNode, nodeExistsForSameUser, policyChanged), nil
}

// createNewNodeFromAuth creates a new node during auth callback.
// This is used for both new registrations and when a machine already has a node
// for a different user.
func (s *State) createNewNodeFromAuth(
	logger zerolog.Logger,
	user *types.User,
	regData *types.RegistrationData,
	hostname string,

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Inspect the wrapped error for the policy-engine cause in server logs
  2. Fix/reload the policy, then trigger any policy update so the node set is rebuilt
  3. Verify with `headscale nodes list` and a peer status check that connectivity converges afterwards
Defensive patterns

Strategy: try-catch

Try / catch

if err != nil && strings.Contains(err.Error(), "updating policy manager nodes") {
    // Registration persisted; node policy view stale until next policy update
    log.Error().Err(err).Msg("node registered; policy nodes refresh pending")
    // self-heal: schedule updatePolicyManagerNodes()
}

Prevention

When it happens

Trigger: updatePolicyManagerNodes() returning an error during the registration callback — policy engine rejecting the node list, or a v2 policy manager internal error while filtering peers.

Common situations: Corrupted or edge-case policy (e.g. autogroup referencing missing entities) that only fails once real nodes are fed in; policy hot-reload racing the callback.

Related errors


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