From 80a34ec3c1c97ffde11ce75fcf96b35c02a308c3 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 2 Feb 2026 14:52:47 +0000 Subject: [PATCH] =?UTF-8?q?state:=20set=20User=20pointer=20during=20tagged?= =?UTF-8?q?=E2=86=92user-owned=20conversion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit processReauthTags sets UserID when converting a tagged node to user-owned, but does not set the User pointer. When the node was registered with a tags-only PreAuthKey (User: nil), the in-memory NodeStore cache holds a node with User=nil. The mapper's generateUserProfiles then calls node.Owner().Model().ID, which dereferences the nil pointer and panics. Set node.User alongside node.UserID in processReauthTags. Also add defensive nil checks in generateUserProfiles to gracefully handle nodes with invalid owners rather than panicking. Fixes #3038 --- hscontrol/mapper/mapper.go | 11 +++++++++++ hscontrol/state/state.go | 1 + 2 files changed, 12 insertions(+) diff --git a/hscontrol/mapper/mapper.go b/hscontrol/mapper/mapper.go index 616d470f..d7807784 100644 --- a/hscontrol/mapper/mapper.go +++ b/hscontrol/mapper/mapper.go @@ -77,11 +77,22 @@ func generateUserProfiles( userMap := make(map[uint]*types.UserView) ids := make([]uint, 0, len(userMap)) user := node.Owner() + if !user.Valid() { + log.Error(). + Uint64("node.id", node.ID().Uint64()). + Str("node.name", node.Hostname()). + Msg("node has no valid owner, skipping user profile generation") + + return nil + } userID := user.Model().ID userMap[userID] = &user ids = append(ids, userID) for _, peer := range peers.All() { peerUser := peer.Owner() + if !peerUser.Valid() { + continue + } peerUserID := peerUser.Model().ID userMap[peerUserID] = &peerUser ids = append(ids, peerUserID) diff --git a/hscontrol/state/state.go b/hscontrol/state/state.go index 5badfc38..48d32766 100644 --- a/hscontrol/state/state.go +++ b/hscontrol/state/state.go @@ -1464,6 +1464,7 @@ func (s *State) processReauthTags( node.Tags = []string{} node.UserID = &user.ID + node.User = user } return nil