From 5a72636042de1af4cdac9dcbbd19200de161c27e Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Thu, 15 Jan 2026 11:47:13 -0800 Subject: [PATCH 1/5] Add dismiss option for NVIDIA driver warning --- src/install/installationManager.ts | 11 ++++++++++- src/store/desktopSettings.ts | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/install/installationManager.ts b/src/install/installationManager.ts index 1f951d751..6bc1cc52c 100644 --- a/src/install/installationManager.ts +++ b/src/install/installationManager.ts @@ -398,19 +398,28 @@ export class InstallationManager implements HasTelemetry { if (process.platform !== 'win32') return; if (installation.virtualEnvironment.selectedDevice !== 'nvidia') return; + const config = useDesktopConfig(); + if (config.get('suppressNvidiaDriverWarning')) return; + const driverVersion = (await this.getNvidiaDriverVersionFromSmi()) ?? (await this.getNvidiaDriverVersionFromSmiFallback()); if (!driverVersion) return; if (!isNvidiaDriverBelowMinimum(driverVersion)) return; - await this.appWindow.showMessageBox({ + const { checkboxChecked } = await this.appWindow.showMessageBox({ type: 'warning', title: 'Update NVIDIA Driver', message: 'Your NVIDIA driver may be too old for PyTorch 2.9.1 + cu130.', detail: `Detected driver version: ${driverVersion}\nRecommended minimum: ${NVIDIA_DRIVER_MIN_VERSION}\n\nPlease consider updating your NVIDIA drivers and retrying if you run into issues.`, buttons: ['OK'], + checkboxLabel: "Don't show again", + checkboxChecked: false, }); + + if (checkboxChecked) { + config.set('suppressNvidiaDriverWarning', true); + } } /** diff --git a/src/store/desktopSettings.ts b/src/store/desktopSettings.ts index 6010253f5..3e199194a 100644 --- a/src/store/desktopSettings.ts +++ b/src/store/desktopSettings.ts @@ -35,4 +35,6 @@ export type DesktopSettings = { versionConsentedMetrics?: string; /** Whether the user has generated an image successfully. */ hasGeneratedSuccessfully?: boolean; + /** Whether the NVIDIA driver warning dialog should be suppressed. */ + suppressNvidiaDriverWarning?: boolean; }; From e8a7fde7042d307fcb98a673507bfa6662381204 Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Thu, 15 Jan 2026 12:17:30 -0800 Subject: [PATCH 2/5] Scope NVIDIA warning dismissal to min driver --- src/install/installationManager.ts | 9 +- src/store/desktopSettings.ts | 4 +- .../unit/install/installationManager.test.ts | 84 ++++++++++++++++++- 3 files changed, 90 insertions(+), 7 deletions(-) diff --git a/src/install/installationManager.ts b/src/install/installationManager.ts index 6bc1cc52c..69b391d17 100644 --- a/src/install/installationManager.ts +++ b/src/install/installationManager.ts @@ -399,7 +399,12 @@ export class InstallationManager implements HasTelemetry { if (installation.virtualEnvironment.selectedDevice !== 'nvidia') return; const config = useDesktopConfig(); - if (config.get('suppressNvidiaDriverWarning')) return; + if (config.get('suppressNvidiaDriverWarningFor') === NVIDIA_DRIVER_MIN_VERSION) return; + if (config.get('suppressNvidiaDriverWarning')) { + config.set('suppressNvidiaDriverWarningFor', NVIDIA_DRIVER_MIN_VERSION); + config.delete('suppressNvidiaDriverWarning'); + return; + } const driverVersion = (await this.getNvidiaDriverVersionFromSmi()) ?? (await this.getNvidiaDriverVersionFromSmiFallback()); @@ -418,7 +423,7 @@ export class InstallationManager implements HasTelemetry { }); if (checkboxChecked) { - config.set('suppressNvidiaDriverWarning', true); + config.set('suppressNvidiaDriverWarningFor', NVIDIA_DRIVER_MIN_VERSION); } } diff --git a/src/store/desktopSettings.ts b/src/store/desktopSettings.ts index 3e199194a..00c2e6139 100644 --- a/src/store/desktopSettings.ts +++ b/src/store/desktopSettings.ts @@ -35,6 +35,8 @@ export type DesktopSettings = { versionConsentedMetrics?: string; /** Whether the user has generated an image successfully. */ hasGeneratedSuccessfully?: boolean; - /** Whether the NVIDIA driver warning dialog should be suppressed. */ + /** @deprecated Use suppressNvidiaDriverWarningFor instead. */ suppressNvidiaDriverWarning?: boolean; + /** The minimum NVIDIA driver version for which the warning was dismissed. */ + suppressNvidiaDriverWarningFor?: string; }; diff --git a/tests/unit/install/installationManager.test.ts b/tests/unit/install/installationManager.test.ts index af9f92969..83b622360 100644 --- a/tests/unit/install/installationManager.test.ts +++ b/tests/unit/install/installationManager.test.ts @@ -33,14 +33,17 @@ vi.mock('node:fs/promises', () => ({ })); const config = { - get: vi.fn((key: string) => { + get: vi.fn((key: string): string | undefined => { if (key === 'installState') return 'installed'; if (key === 'basePath') return 'valid/base'; + return undefined; }), - set: vi.fn((key: string, value: string) => { - if (key !== 'basePath') throw new Error(`Unexpected key: ${key}`); - if (!value) throw new Error(`Unexpected value: [${value}]`); + set: vi.fn((key: string, value: unknown) => { + const allowedKeys = new Set(['basePath', 'suppressNvidiaDriverWarning', 'suppressNvidiaDriverWarningFor']); + if (!allowedKeys.has(key)) throw new Error(`Unexpected key: ${key}`); + if (key === 'basePath' && !value) throw new Error(`Unexpected value: [${value}]`); }), + delete: vi.fn(), }; vi.mock('@/store/desktopConfig', () => ({ useDesktopConfig: vi.fn(() => config), @@ -110,6 +113,7 @@ const createMockAppWindow = () => { send: vi.fn(), loadPage: vi.fn(() => Promise.resolve(null)), showOpenDialog: vi.fn(), + showMessageBox: vi.fn(() => Promise.resolve({ response: 0, checkboxChecked: false })), maximize: vi.fn(), }; return mock as unknown as AppWindow; @@ -251,6 +255,78 @@ describe('InstallationManager', () => { cleanup?.(); }); }); + + describe('warnIfNvidiaDriverTooOld', () => { + const createInstallation = (device: string) => + ({ virtualEnvironment: { selectedDevice: device } }) as ComfyInstallation; + + const getManagerMethods = () => + manager as unknown as { + warnIfNvidiaDriverTooOld: (installation: ComfyInstallation) => Promise; + getNvidiaDriverVersionFromSmi: () => Promise; + getNvidiaDriverVersionFromSmiFallback: () => Promise; + }; + + beforeEach(() => { + vi.mocked(config.get).mockImplementation((key: string) => { + if (key === 'installState') return 'installed'; + if (key === 'basePath') return 'valid/base'; + return undefined; + }); + vi.mocked(config.set).mockClear(); + vi.mocked(config.delete).mockClear(); + vi.mocked(mockAppWindow.showMessageBox).mockClear(); + }); + + it('skips dialog when warning is suppressed for the current minimum version', async () => { + const platformSpy = vi.spyOn(process, 'platform', 'get').mockReturnValue('win32'); + const managerMethods = getManagerMethods(); + const smiSpy = vi.spyOn(managerMethods, 'getNvidiaDriverVersionFromSmi').mockResolvedValue('570.0'); + const smiFallbackSpy = vi + .spyOn(managerMethods, 'getNvidiaDriverVersionFromSmiFallback') + .mockResolvedValue(undefined); + + try { + vi.mocked(config.get).mockImplementation((key: string) => { + if (key === 'installState') return 'installed'; + if (key === 'basePath') return 'valid/base'; + if (key === 'suppressNvidiaDriverWarningFor') return '580'; + return undefined; + }); + + await managerMethods.warnIfNvidiaDriverTooOld(createInstallation('nvidia')); + + expect(smiSpy).not.toHaveBeenCalled(); + expect(smiFallbackSpy).not.toHaveBeenCalled(); + expect(mockAppWindow.showMessageBox).not.toHaveBeenCalled(); + } finally { + smiSpy.mockRestore(); + smiFallbackSpy.mockRestore(); + platformSpy.mockRestore(); + } + }); + + it('stores the current minimum version when dismissed', async () => { + const platformSpy = vi.spyOn(process, 'platform', 'get').mockReturnValue('win32'); + const managerMethods = getManagerMethods(); + const smiSpy = vi.spyOn(managerMethods, 'getNvidiaDriverVersionFromSmi').mockResolvedValue('570.0'); + const smiFallbackSpy = vi + .spyOn(managerMethods, 'getNvidiaDriverVersionFromSmiFallback') + .mockResolvedValue(undefined); + + try { + vi.mocked(mockAppWindow.showMessageBox).mockResolvedValue({ response: 0, checkboxChecked: true }); + + await managerMethods.warnIfNvidiaDriverTooOld(createInstallation('nvidia')); + + expect(config.set).toHaveBeenCalledWith('suppressNvidiaDriverWarningFor', '580'); + } finally { + smiSpy.mockRestore(); + smiFallbackSpy.mockRestore(); + platformSpy.mockRestore(); + } + }); + }); }); describe('parseNvidiaDriverVersionFromSmiOutput', () => { From 3910bc7c1b914dc0d86df4219f825391b3ba2306 Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Thu, 15 Jan 2026 12:19:32 -0800 Subject: [PATCH 3/5] Drop legacy Nvidia warning suppression flag --- src/install/installationManager.ts | 5 ----- src/store/desktopSettings.ts | 2 -- tests/unit/install/installationManager.test.ts | 4 +--- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/install/installationManager.ts b/src/install/installationManager.ts index 69b391d17..d18e9b80a 100644 --- a/src/install/installationManager.ts +++ b/src/install/installationManager.ts @@ -400,11 +400,6 @@ export class InstallationManager implements HasTelemetry { const config = useDesktopConfig(); if (config.get('suppressNvidiaDriverWarningFor') === NVIDIA_DRIVER_MIN_VERSION) return; - if (config.get('suppressNvidiaDriverWarning')) { - config.set('suppressNvidiaDriverWarningFor', NVIDIA_DRIVER_MIN_VERSION); - config.delete('suppressNvidiaDriverWarning'); - return; - } const driverVersion = (await this.getNvidiaDriverVersionFromSmi()) ?? (await this.getNvidiaDriverVersionFromSmiFallback()); diff --git a/src/store/desktopSettings.ts b/src/store/desktopSettings.ts index 00c2e6139..21bb13e22 100644 --- a/src/store/desktopSettings.ts +++ b/src/store/desktopSettings.ts @@ -35,8 +35,6 @@ export type DesktopSettings = { versionConsentedMetrics?: string; /** Whether the user has generated an image successfully. */ hasGeneratedSuccessfully?: boolean; - /** @deprecated Use suppressNvidiaDriverWarningFor instead. */ - suppressNvidiaDriverWarning?: boolean; /** The minimum NVIDIA driver version for which the warning was dismissed. */ suppressNvidiaDriverWarningFor?: string; }; diff --git a/tests/unit/install/installationManager.test.ts b/tests/unit/install/installationManager.test.ts index 83b622360..9197f8365 100644 --- a/tests/unit/install/installationManager.test.ts +++ b/tests/unit/install/installationManager.test.ts @@ -39,11 +39,10 @@ const config = { return undefined; }), set: vi.fn((key: string, value: unknown) => { - const allowedKeys = new Set(['basePath', 'suppressNvidiaDriverWarning', 'suppressNvidiaDriverWarningFor']); + const allowedKeys = new Set(['basePath', 'suppressNvidiaDriverWarningFor']); if (!allowedKeys.has(key)) throw new Error(`Unexpected key: ${key}`); if (key === 'basePath' && !value) throw new Error(`Unexpected value: [${value}]`); }), - delete: vi.fn(), }; vi.mock('@/store/desktopConfig', () => ({ useDesktopConfig: vi.fn(() => config), @@ -274,7 +273,6 @@ describe('InstallationManager', () => { return undefined; }); vi.mocked(config.set).mockClear(); - vi.mocked(config.delete).mockClear(); vi.mocked(mockAppWindow.showMessageBox).mockClear(); }); From 48a1699c0c213d977bad7ab23476901ca294420c Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Thu, 15 Jan 2026 15:37:54 -0800 Subject: [PATCH 4/5] Use min driver constant in tests --- src/install/installationManager.ts | 2 +- tests/unit/install/installationManager.test.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/install/installationManager.ts b/src/install/installationManager.ts index d18e9b80a..2eafd67be 100644 --- a/src/install/installationManager.ts +++ b/src/install/installationManager.ts @@ -23,7 +23,7 @@ import { InstallWizard } from './installWizard'; import { Troubleshooting } from './troubleshooting'; const execAsync = promisify(exec); -const NVIDIA_DRIVER_MIN_VERSION = '580'; +export const NVIDIA_DRIVER_MIN_VERSION = '580'; /** * Extracts the NVIDIA driver version from `nvidia-smi` output. diff --git a/tests/unit/install/installationManager.test.ts b/tests/unit/install/installationManager.test.ts index 9197f8365..fcba280cf 100644 --- a/tests/unit/install/installationManager.test.ts +++ b/tests/unit/install/installationManager.test.ts @@ -7,6 +7,7 @@ import { ComfySettings } from '@/config/comfySettings'; import { IPC_CHANNELS } from '@/constants'; import { InstallationManager, + NVIDIA_DRIVER_MIN_VERSION, isNvidiaDriverBelowMinimum, parseNvidiaDriverVersionFromSmiOutput, } from '@/install/installationManager'; @@ -288,7 +289,7 @@ describe('InstallationManager', () => { vi.mocked(config.get).mockImplementation((key: string) => { if (key === 'installState') return 'installed'; if (key === 'basePath') return 'valid/base'; - if (key === 'suppressNvidiaDriverWarningFor') return '580'; + if (key === 'suppressNvidiaDriverWarningFor') return NVIDIA_DRIVER_MIN_VERSION; return undefined; }); @@ -317,7 +318,7 @@ describe('InstallationManager', () => { await managerMethods.warnIfNvidiaDriverTooOld(createInstallation('nvidia')); - expect(config.set).toHaveBeenCalledWith('suppressNvidiaDriverWarningFor', '580'); + expect(config.set).toHaveBeenCalledWith('suppressNvidiaDriverWarningFor', NVIDIA_DRIVER_MIN_VERSION); } finally { smiSpy.mockRestore(); smiFallbackSpy.mockRestore(); From 47491c09d2c6f4b3d0f17b3503542a8dd104cc89 Mon Sep 17 00:00:00 2001 From: Benjamin Lu Date: Thu, 15 Jan 2026 17:08:31 -0800 Subject: [PATCH 5/5] Add NVIDIA driver warning helper --- src/install/installationManager.ts | 48 +++++- .../unit/install/installationManager.test.ts | 137 +++++++++--------- 2 files changed, 114 insertions(+), 71 deletions(-) diff --git a/src/install/installationManager.ts b/src/install/installationManager.ts index 2eafd67be..754dfbc80 100644 --- a/src/install/installationManager.ts +++ b/src/install/installationManager.ts @@ -11,7 +11,7 @@ import { useAppState } from '../main-process/appState'; import type { AppWindow } from '../main-process/appWindow'; import { ComfyInstallation } from '../main-process/comfyInstallation'; import { createInstallStageInfo } from '../main-process/installStages'; -import type { InstallOptions, InstallValidation } from '../preload'; +import type { InstallOptions, InstallValidation, TorchDeviceType } from '../preload'; import { CmCli } from '../services/cmCli'; import { captureSentryException } from '../services/sentry'; import { type HasTelemetry, ITelemetry, trackEvent } from '../services/telemetry'; @@ -47,6 +47,36 @@ export function isNvidiaDriverBelowMinimum( return compareVersions(driverVersion, minimumVersion) < 0; } +type NvidiaDriverWarningContext = { + platform: NodeJS.Platform; + selectedDevice?: TorchDeviceType; + suppressWarningFor?: string; + driverVersion?: string; + minimumVersion?: string; +}; + +/** + * Determines whether the NVIDIA driver warning should be shown. + * @param context The driver warning context. + * @return `true` when the warning should be shown. + */ +export function shouldWarnAboutNvidiaDriver(context: NvidiaDriverWarningContext): boolean { + const { + platform, + selectedDevice, + suppressWarningFor, + driverVersion, + minimumVersion = NVIDIA_DRIVER_MIN_VERSION, + } = context; + + if (platform !== 'win32') return false; + if (selectedDevice !== 'nvidia') return false; + if (suppressWarningFor === minimumVersion) return false; + if (!driverVersion) return false; + + return isNvidiaDriverBelowMinimum(driverVersion, minimumVersion); +} + /** High-level / UI control over the installation of ComfyUI server. */ export class InstallationManager implements HasTelemetry { constructor( @@ -399,13 +429,21 @@ export class InstallationManager implements HasTelemetry { if (installation.virtualEnvironment.selectedDevice !== 'nvidia') return; const config = useDesktopConfig(); - if (config.get('suppressNvidiaDriverWarningFor') === NVIDIA_DRIVER_MIN_VERSION) return; + const suppressWarningFor = config.get('suppressNvidiaDriverWarningFor'); + if (suppressWarningFor === NVIDIA_DRIVER_MIN_VERSION) return; const driverVersion = (await this.getNvidiaDriverVersionFromSmi()) ?? (await this.getNvidiaDriverVersionFromSmiFallback()); - if (!driverVersion) return; - - if (!isNvidiaDriverBelowMinimum(driverVersion)) return; + if ( + !shouldWarnAboutNvidiaDriver({ + platform: process.platform, + selectedDevice: installation.virtualEnvironment.selectedDevice, + suppressWarningFor, + driverVersion, + }) + ) { + return; + } const { checkboxChecked } = await this.appWindow.showMessageBox({ type: 'warning', diff --git a/tests/unit/install/installationManager.test.ts b/tests/unit/install/installationManager.test.ts index fcba280cf..3a3d4b938 100644 --- a/tests/unit/install/installationManager.test.ts +++ b/tests/unit/install/installationManager.test.ts @@ -10,6 +10,7 @@ import { NVIDIA_DRIVER_MIN_VERSION, isNvidiaDriverBelowMinimum, parseNvidiaDriverVersionFromSmiOutput, + shouldWarnAboutNvidiaDriver, } from '@/install/installationManager'; import type { AppWindow } from '@/main-process/appWindow'; import { ComfyInstallation } from '@/main-process/comfyInstallation'; @@ -256,74 +257,78 @@ describe('InstallationManager', () => { }); }); - describe('warnIfNvidiaDriverTooOld', () => { - const createInstallation = (device: string) => - ({ virtualEnvironment: { selectedDevice: device } }) as ComfyInstallation; + describe('shouldWarnAboutNvidiaDriver', () => { + type NvidiaDriverWarningInput = Parameters[0]; - const getManagerMethods = () => - manager as unknown as { - warnIfNvidiaDriverTooOld: (installation: ComfyInstallation) => Promise; - getNvidiaDriverVersionFromSmi: () => Promise; - getNvidiaDriverVersionFromSmiFallback: () => Promise; - }; - - beforeEach(() => { - vi.mocked(config.get).mockImplementation((key: string) => { - if (key === 'installState') return 'installed'; - if (key === 'basePath') return 'valid/base'; - return undefined; - }); - vi.mocked(config.set).mockClear(); - vi.mocked(mockAppWindow.showMessageBox).mockClear(); - }); - - it('skips dialog when warning is suppressed for the current minimum version', async () => { - const platformSpy = vi.spyOn(process, 'platform', 'get').mockReturnValue('win32'); - const managerMethods = getManagerMethods(); - const smiSpy = vi.spyOn(managerMethods, 'getNvidiaDriverVersionFromSmi').mockResolvedValue('570.0'); - const smiFallbackSpy = vi - .spyOn(managerMethods, 'getNvidiaDriverVersionFromSmiFallback') - .mockResolvedValue(undefined); - - try { - vi.mocked(config.get).mockImplementation((key: string) => { - if (key === 'installState') return 'installed'; - if (key === 'basePath') return 'valid/base'; - if (key === 'suppressNvidiaDriverWarningFor') return NVIDIA_DRIVER_MIN_VERSION; - return undefined; - }); - - await managerMethods.warnIfNvidiaDriverTooOld(createInstallation('nvidia')); - - expect(smiSpy).not.toHaveBeenCalled(); - expect(smiFallbackSpy).not.toHaveBeenCalled(); - expect(mockAppWindow.showMessageBox).not.toHaveBeenCalled(); - } finally { - smiSpy.mockRestore(); - smiFallbackSpy.mockRestore(); - platformSpy.mockRestore(); - } - }); - - it('stores the current minimum version when dismissed', async () => { - const platformSpy = vi.spyOn(process, 'platform', 'get').mockReturnValue('win32'); - const managerMethods = getManagerMethods(); - const smiSpy = vi.spyOn(managerMethods, 'getNvidiaDriverVersionFromSmi').mockResolvedValue('570.0'); - const smiFallbackSpy = vi - .spyOn(managerMethods, 'getNvidiaDriverVersionFromSmiFallback') - .mockResolvedValue(undefined); - - try { - vi.mocked(mockAppWindow.showMessageBox).mockResolvedValue({ response: 0, checkboxChecked: true }); - - await managerMethods.warnIfNvidiaDriverTooOld(createInstallation('nvidia')); + const scenarios: Array<{ + scenario: string; + input: NvidiaDriverWarningInput; + expected: boolean; + }> = [ + { + scenario: 'returns false on non-Windows platforms', + input: { + platform: 'darwin', + selectedDevice: 'nvidia', + driverVersion: '570.0', + suppressWarningFor: undefined, + }, + expected: false, + }, + { + scenario: 'returns false when device is not nvidia', + input: { + platform: 'win32', + selectedDevice: 'cpu', + driverVersion: '570.0', + suppressWarningFor: undefined, + }, + expected: false, + }, + { + scenario: 'returns false when warning is suppressed for the minimum version', + input: { + platform: 'win32', + selectedDevice: 'nvidia', + driverVersion: '570.0', + suppressWarningFor: NVIDIA_DRIVER_MIN_VERSION, + }, + expected: false, + }, + { + scenario: 'returns false when driver version is missing', + input: { + platform: 'win32', + selectedDevice: 'nvidia', + driverVersion: undefined, + suppressWarningFor: undefined, + }, + expected: false, + }, + { + scenario: 'returns true when driver is below minimum', + input: { + platform: 'win32', + selectedDevice: 'nvidia', + driverVersion: '579.0.0', + suppressWarningFor: undefined, + }, + expected: true, + }, + { + scenario: 'returns false when driver meets minimum', + input: { + platform: 'win32', + selectedDevice: 'nvidia', + driverVersion: '580.0.0', + suppressWarningFor: undefined, + }, + expected: false, + }, + ]; - expect(config.set).toHaveBeenCalledWith('suppressNvidiaDriverWarningFor', NVIDIA_DRIVER_MIN_VERSION); - } finally { - smiSpy.mockRestore(); - smiFallbackSpy.mockRestore(); - platformSpy.mockRestore(); - } + it.each(scenarios)('$scenario', ({ input, expected }) => { + expect(shouldWarnAboutNvidiaDriver(input)).toBe(expected); }); }); });