Note
Grok responding on behalf of Julius.
Triage
Thanks for such a careful report, @TonybynMp4! There are two separate failures here, and you split them correctly. First, the .deb install never reaches pkexec from an instance that app.relaunch() started. Second, the first Restart click doesn't say it failed. Quitting and relaunching from the desktop is a real workaround. This is also not the same as open #13977: that issue is about the generic log line, and this one is an install that never runs.
Missing journal lines. These come from Electron, not the updater. Desktop is on Electron 44.4.2. On Linux, app.relaunch() goes through relauncher_linux.cc, which starts a new process group and points the child's stdout and stderr at /dev/null. A normal desktop launch stays in the systemd user scope, so electron-updater's console lines (Running as non-root user, using sudo to install: pkexec,--disable-internal-agent, Executing: ...) show up under t3code.desktop. After a relaunch they don't. desktop.trace.ndjson still works because that logger writes to a file. That explains the log gap, but not which check rejected the install.
Which check fails. electron-updater 6.8.9 only dispatchErrors before runCommandWithSudoIfNeeded in two places, and both match "no pkexec, polkit, or sudo entry":
BaseUpdater.install, wheninstallerPathordownloadedFileInfois null:No update filepath provided, can't quit and install.DebUpdater.doInstall, when bothhasCommand("dpkg")andhasCommand("apt")are false:Neither dpkg nor apt command found. Cannot install .deb package.
hasCommand is spawnSyncLog("command", ["-v", cmd]), and it swallows every throw, including a non-zero command -v. So a probe exception isn't its own error; if both probes fail, you get the plain "Neither dpkg nor apt" Error. There's no third path before pkexec. These logs can't tell us which of the two it was.
Open PR #14008 won't classify either one. Both are plain Errors with no code and no Command … exited with code N text, so errorCode and exitStatus stay empty. An exit status only shows up if the install gets as far as spawning pkexec or sudo. The constraint from #13977 still applies: don't log error.cause, and don't hand electron-updater's logger to the desktop log unchanged, because download and install lines can include the feed URL. A bounded reason like no-installer-path or no-package-manager fits as the discriminator. The raw Executing: text doesn't.
Silent first click. This one is in our handler, not in quitAndInstall. DebUpdater.doInstall emits error and returns false. quitAndInstall doesn't throw, so ElectronUpdaterQuitAndInstallError never happens, and installDownloadedUpdate returns { accepted: true, completed: false }. DesktopUpdates.install drops the internal failed flag before IPC, since DesktopUpdateActionResult has no failed field, and the toast only reads state.message via getDesktopUpdateActionError. Meanwhile handleUpdaterError runs on another fiber, and recoverFailedInstall only writes the message after the backends restart. So the click returns while message is still null, and no toast shows. The next click is allowed because errorContext === "install", and it picks up the message the previous recovery left behind. That's why the toast shows up late and only says Desktop updater install operation reported an error. Returning failed: true alone won't fix the toast; the message has to be on state before install reads it.