Clicking Ignore skips replacing the exe, so the app silently stays on the old version and the same update is offered again next time.
Immediate workaround: click Retry instead of Ignore. By then the old process has exited and the write succeeds.
Analysis
install_update (src-tauri/src/lib.rs) calls update.download_and_install(...). On Windows, tauri-plugin-updater 2.10.1 spawns the NSIS installer with /P /R (passive + relaunch), runs the on_before_exit hook, then std::process::exit(0) (updater.rs ~L838-865). The installer therefore starts while the old cinny.exe is still alive and immediately tries to overwrite it; if the process (WebView2 teardown, tray, single-instance) hasn't fully released the file yet, NSIS hits the lock. Our app.restart() after the install call is never reached on Windows (the plugin has already exited), so it isn't the cause, but it is dead code on that platform.
Candidate fixes (need a Windows build to verify)
Register an on_before_exit hook via app.updater_builder().on_before_exit(...) that closes all webview windows and removes the tray icon so the exe handle is released before NSIS runs, and check whether the bundled NSIS template's running-app check (nsis_tauri_utils::FindProcess / kill in update mode) is actually active for /P passive installs in this Tauri version.
If that isn't enough: update.download() to a temp file ourselves and launch the installer detached via cmd /c "timeout /t 2 >nul && start "" "<installer>" /P /R" before app.exit(0), giving the process time to die. Uglier, but deterministic.
Alternatively switch plugins.updater.windows.installMode to quiet (/S /R) and confirm whether the silent path force-closes the running app (Tauri's template behaves differently in silent vs passive mode).
Related: the "update available" state losing on Settings close is fixed in cinny (useTauriUpdater now keeps it in a shared atom).
**Symptom (Windows, last two auto-updates):** the NSIS installer window pops up with
> Error opening file for writing: `C:\Users\<user>\AppData\Local\Lotus Chat\cinny.exe` — Abort / Retry / Ignore
Clicking **Ignore** skips replacing the exe, so the app silently stays on the old version and the same update is offered again next time.
**Immediate workaround:** click **Retry** instead of Ignore. By then the old process has exited and the write succeeds.
### Analysis
`install_update` (src-tauri/src/lib.rs) calls `update.download_and_install(...)`. On Windows, `tauri-plugin-updater` 2.10.1 spawns the NSIS installer with `/P /R` (passive + relaunch), runs the `on_before_exit` hook, then `std::process::exit(0)` (updater.rs ~L838-865). The installer therefore starts *while the old `cinny.exe` is still alive* and immediately tries to overwrite it; if the process (WebView2 teardown, tray, single-instance) hasn't fully released the file yet, NSIS hits the lock. Our `app.restart()` after the install call is never reached on Windows (the plugin has already exited), so it isn't the cause, but it is dead code on that platform.
### Candidate fixes (need a Windows build to verify)
1. Register an `on_before_exit` hook via `app.updater_builder().on_before_exit(...)` that closes all webview windows and removes the tray icon so the exe handle is released before NSIS runs, and check whether the bundled NSIS template's running-app check (`nsis_tauri_utils::FindProcess` / kill in update mode) is actually active for `/P` passive installs in this Tauri version.
2. If that isn't enough: `update.download()` to a temp file ourselves and launch the installer detached via `cmd /c "timeout /t 2 >nul && start "" "<installer>" /P /R"` before `app.exit(0)`, giving the process time to die. Uglier, but deterministic.
3. Alternatively switch `plugins.updater.windows.installMode` to `quiet` (`/S /R`) and confirm whether the silent path force-closes the running app (Tauri's template behaves differently in silent vs passive mode).
Related: the "update available" state losing on Settings close is fixed in cinny (`useTauriUpdater` now keeps it in a shared atom).
jared
self-assigned this 2026-09-15 08:47:06 -04:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Symptom (Windows, last two auto-updates): the NSIS installer window pops up with
Clicking Ignore skips replacing the exe, so the app silently stays on the old version and the same update is offered again next time.
Immediate workaround: click Retry instead of Ignore. By then the old process has exited and the write succeeds.
Analysis
install_update(src-tauri/src/lib.rs) callsupdate.download_and_install(...). On Windows,tauri-plugin-updater2.10.1 spawns the NSIS installer with/P /R(passive + relaunch), runs theon_before_exithook, thenstd::process::exit(0)(updater.rs ~L838-865). The installer therefore starts while the oldcinny.exeis still alive and immediately tries to overwrite it; if the process (WebView2 teardown, tray, single-instance) hasn't fully released the file yet, NSIS hits the lock. Ourapp.restart()after the install call is never reached on Windows (the plugin has already exited), so it isn't the cause, but it is dead code on that platform.Candidate fixes (need a Windows build to verify)
on_before_exithook viaapp.updater_builder().on_before_exit(...)that closes all webview windows and removes the tray icon so the exe handle is released before NSIS runs, and check whether the bundled NSIS template's running-app check (nsis_tauri_utils::FindProcess/ kill in update mode) is actually active for/Ppassive installs in this Tauri version.update.download()to a temp file ourselves and launch the installer detached viacmd /c "timeout /t 2 >nul && start "" "<installer>" /P /R"beforeapp.exit(0), giving the process time to die. Uglier, but deterministic.plugins.updater.windows.installModetoquiet(/S /R) and confirm whether the silent path force-closes the running app (Tauri's template behaves differently in silent vs passive mode).Related: the "update available" state losing on Settings close is fixed in cinny (
useTauriUpdaternow keeps it in a shared atom).