From 4db7643a6bc020c94ff9997db6889a7a4e1e4a16 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Fri, 20 Mar 2026 20:47:21 -0700 Subject: [PATCH] Fix update checker 406 error and add menu feedback dialogs The GitHub /releases/latest endpoint returns 406 when electron-updater requests it with Accept: application/json. Setting allowPrerelease=true bypasses this by parsing the version from the atom feed directly. The "Check for Updates" menu item now shows native dialogs so users get feedback without needing to open Settings. Co-Authored-By: Claude Opus 4.6 --- src/main/index.ts | 10 +++++++-- src/main/updater.ts | 52 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 8d432d5f281..bca05a3b85c 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -14,7 +14,13 @@ import { registerShellHandlers } from './ipc/shell' import { registerSessionHandlers } from './ipc/session' import { registerUIHandlers } from './ipc/ui' import { warmSystemFontFamilies } from './system-fonts' -import { setupAutoUpdater, checkForUpdates, getUpdateStatus, quitAndInstall } from './updater' +import { + setupAutoUpdater, + checkForUpdates, + checkForUpdatesFromMenu, + getUpdateStatus, + quitAndInstall +} from './updater' let mainWindow: BrowserWindow | null = null let store: Store | null = null @@ -113,7 +119,7 @@ app.whenReady().then(() => { { role: 'about' }, { label: 'Check for Updates...', - click: () => checkForUpdates() + click: () => checkForUpdatesFromMenu() }, { label: 'Settings', diff --git a/src/main/updater.ts b/src/main/updater.ts index 8cf25c7c614..5b6674ad9f1 100644 --- a/src/main/updater.ts +++ b/src/main/updater.ts @@ -26,6 +26,54 @@ export function checkForUpdates(): void { }) } +/** Menu-triggered check that shows native dialogs for feedback */ +export function checkForUpdatesFromMenu(): void { + if (!app.isPackaged || is.dev) { + dialog.showMessageBox({ type: 'info', message: 'You\u2019re on the latest version.' }) + return + } + + sendStatus({ state: 'checking' }) + + const onAvailable = (): void => { + cleanup() + } + const onNotAvailable = (): void => { + cleanup() + dialog.showMessageBox({ type: 'info', message: 'You\u2019re on the latest version.' }) + } + const onError = (err: Error): void => { + cleanup() + dialog.showMessageBox({ + type: 'error', + title: 'Update Error', + message: 'Could not check for updates.', + detail: err?.message + }) + } + + function cleanup(): void { + autoUpdater.off('update-available', onAvailable) + autoUpdater.off('update-not-available', onNotAvailable) + autoUpdater.off('error', onError) + } + + autoUpdater.once('update-available', onAvailable) + autoUpdater.once('update-not-available', onNotAvailable) + autoUpdater.once('error', onError) + + autoUpdater.checkForUpdates().catch((err) => { + sendStatus({ state: 'error', message: String(err?.message ?? err) }) + cleanup() + dialog.showMessageBox({ + type: 'error', + title: 'Update Error', + message: 'Could not check for updates.', + detail: String(err?.message ?? err) + }) + }) +} + export function quitAndInstall(): void { autoUpdater.quitAndInstall() } @@ -38,6 +86,10 @@ export function setupAutoUpdater(mainWindow: BrowserWindow): void { autoUpdater.autoDownload = true autoUpdater.autoInstallOnAppQuit = true + // Use allowPrerelease to bypass broken /releases/latest endpoint (returns 406) + // and instead parse the version directly from the atom feed which works reliably. + // This is safe since we don't publish prerelease versions. + autoUpdater.allowPrerelease = true autoUpdater.on('checking-for-update', () => { sendStatus({ state: 'checking' })