diff --git a/pkg/accessreview/source_name_worker.go b/pkg/accessreview/source_name_worker.go index 2f2a248a9..8b10dc929 100644 --- a/pkg/accessreview/source_name_worker.go +++ b/pkg/accessreview/source_name_worker.go @@ -146,14 +146,23 @@ func (h *sourceNameHandler) Process(ctx context.Context, source coredata.AccessR }, ) if err != nil { - h.logger.ErrorCtx( + // Setting up the resolver failed: the connector is gone, its + // credentials cannot be decrypted, or an eager token refresh failed + // on a revoked OAuth refresh token. Returning nil without marking the + // source synced leaves name_synced_at NULL, so the worker re-claims + // the same row every drain cycle with no delay — a single dead + // connector then hot-loops the vendor token endpoint (millions of + // error logs in prod). Treat it as terminal: keep the generic name + // and mark the source synced so it stops re-claiming. A + // reconnect/reconfigure clears name_synced_at to try again. + h.logger.WarnCtx( ctx, - "cannot load connector for source name sync", + "cannot set up name resolver, keeping generic name", log.String("source_id", source.ID.String()), log.Error(err), ) - return nil + return h.markNameSynced(ctx, &source) } if resolver == nil {