From e36fef869278ec75f7a8b5e9c51ac02ab600de71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deluan=20Quint=C3=A3o?= Date: Fri, 28 Nov 2025 19:38:28 -0500 Subject: [PATCH] fix: retry insights collection when no admin user available (#4746) Previously, the insights collector would only try to get an admin user once at startup. If no admin user existed (e.g., fresh database before first user registration), insights collection would silently fail forever. This change moves the admin context creation inside the collection loop so it retries on each interval. It also updates log messages in WithAdminUser to remove the Scanner prefix since this function is now used by other components. Signed-off-by: Deluan --- core/auth/auth.go | 4 ++-- core/metrics/insights.go | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/core/auth/auth.go b/core/auth/auth.go index fd2b670a4..ddd12767b 100644 --- a/core/auth/auth.go +++ b/core/auth/auth.go @@ -113,9 +113,9 @@ func WithAdminUser(ctx context.Context, ds model.DataStore) context.Context { if err != nil { c, err := ds.User(ctx).CountAll() if c == 0 && err == nil { - log.Debug(ctx, "Scanner: No admin user yet!", err) + log.Debug(ctx, "No admin user yet!", err) } else { - log.Error(ctx, "Scanner: No admin user found!", err) + log.Error(ctx, "No admin user found!", err) } u = &model.User{} } diff --git a/core/metrics/insights.go b/core/metrics/insights.go index 010c24c28..820e6d7b6 100644 --- a/core/metrics/insights.go +++ b/core/metrics/insights.go @@ -22,6 +22,7 @@ import ( "github.com/navidrome/navidrome/core/metrics/insights" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" + "github.com/navidrome/navidrome/model/request" "github.com/navidrome/navidrome/plugins/schema" "github.com/navidrome/navidrome/utils/singleton" ) @@ -64,9 +65,16 @@ func GetInstance(ds model.DataStore, pluginLoader PluginLoader) Insights { } func (c *insightsCollector) Run(ctx context.Context) { - ctx = auth.WithAdminUser(ctx, c.ds) for { - c.sendInsights(ctx) + // Refresh admin context on each iteration to handle cases where + // admin user wasn't available on previous runs + insightsCtx := auth.WithAdminUser(ctx, c.ds) + u, _ := request.UserFrom(insightsCtx) + if !u.IsAdmin { + log.Trace(insightsCtx, "No admin user available, skipping insights collection") + } else { + c.sendInsights(insightsCtx) + } select { case <-time.After(consts.InsightsUpdateInterval): continue