From 8841b950a2346a4fd6631882573b4bdaa6f8c283 Mon Sep 17 00:00:00 2001 From: Zoltan Papp Date: Mon, 11 May 2026 13:43:53 +0200 Subject: [PATCH] [client/server] Stop retry loop after PermissionDenied login Without marking the error as backoff.Permanent the outer retry re-enters connect(), which resets the daemon state from NeedsLogin to Connecting and makes the tray flicker between the two until the user logs in. --- client/server/server.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/server/server.go b/client/server/server.go index 55d166fdb..a79e49457 100644 --- a/client/server/server.go +++ b/client/server/server.go @@ -258,6 +258,15 @@ func (s *Server) connectWithRetryRuns(ctx context.Context, profileConfig *profil runOperation := func() error { err := s.connect(ctx, profileConfig, statusRecorder, runningChan) if err != nil { + // PermissionDenied means the daemon transitioned to NeedsLogin + // inside connect(). Without backoff.Permanent the outer retry + // re-enters connect(), which resets the state to Connecting and + // makes the tray flicker between NeedsLogin and Connecting until + // the user logs in. Stop retrying and let the state stick. + if s, ok := gstatus.FromError(err); ok && s.Code() == codes.PermissionDenied { + log.Debugf("run client connection exited with PermissionDenied, waiting for login") + return backoff.Permanent(err) + } log.Debugf("run client connection exited with error: %v. Will retry in the background", err) return err }