-
Notifications
You must be signed in to change notification settings - Fork 17.1k
autoUpdater.quitAndInstall() fails to apply update and app does not relaunch #50200
Description
Preflight Checklist
- I have read the Contributing Guidelines for this project.
- I agree to follow the Code of Conduct that this project adheres to.
- I have searched the issue tracker for a bug report that matches the one I want to file, without success.
Electron Version
39.6.0
What operating system(s) are you using?
macOS
Operating System Version
Unsure (not my machine)
What arch are you using?
arm64 (including Apple Silicon)
Last Known Working Electron version
No response
Does the issue also appear in Chromium / Google Chrome?
No
Expected Behavior
After 'update-downloaded', calling autoUpdater.quitAndInstall() will apply the update and restart the app.
Actual Behavior
I have privately received a report that autoUpdater.quitAndInstall() no longer consistently applies updates and restarts the app in a very popular Electron application on macOS.
The new version is downloaded, but on autoUpdater.quitAndInstall() the app never relaunches.
This started happening after upgrading to Electron 39.6.0. It does not happen on every update, but it happens often enough to be a problem.
When the issue occurs, the following logs are printed:
2026-03-07 14:15:48.938 ShipIt[91919:9806597] Installation error: Error Domain=SQRLInstallerErrorDomain Code=-1 "Failed to copy bundle file:///Users/name/Library/Caches/com.appname.ShipIt/update.0vPlgMV/Name.app/ to directory file:///var/folders/xr/4nvbvbf97td72pr6qh1mm4p00000gn/T/com.appname.ShipIt.QHGrIddV/Name.app" UserInfo={NSLocalizedDescription=Failed to copy bundle file:///Users/name/Library/Caches/com.appname.ShipIt/update.0vPlgMV/Name.app/ to directory file:///var/folders/xr/4nvbvbf97td72pr6qh1mm4p00000gn/T/com.appname.ShipIt.QHGrIddV/Name.app, NSFilePath=/Users/name/Library/Caches/com.appname.ShipIt/update.0vPlgMV/Name.app, NSURL=file:///Users/name/Library/Caches/com.appname.ShipIt/update.0vPlgMV/Name.app, NSUnderlyingError=0x95b014600 {Error Domain=NSCocoaErrorDomain Code=260 "The file "Name.app" couldn't be opened because there is no such file." UserInfo={NSFilePath=/Users/name/Library/Caches/com.appname.ShipIt/update.0vPlgMV/Name.app, NSURL=file:///Users/name/Library/Caches/com.appname.ShipIt/update.0vPlgMV/Name.app, NSUnderlyingError=0x95b0145a0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}}}
2026-03-07 14:15:48.938 ShipIt[91919:9806597] ShipIt quitting
2026-03-07 14:15:51.005 ShipIt[91926:9806656] Detected this as an install request
2026-03-07 14:15:51.020 ShipIt[91926:9806656] Too many attempts to install, aborting update
2026-03-07 14:15:51.021 ShipIt[91926:9806656] ShipIt quitting
The important part is:
The file "Name.app" couldn't be opened because there is no such file.
Testcase Gist URL
No response
Additional Information
This seems like a consequence of #49365, backported to Electron 39.6.0.
That PR introduced logic to remove previously downloaded updates when autoUpdater.checkForUpdates() is called.
It's easy to imagine a race condition such as the following:
autoUpdater.checkForUpdates()is called- An update is downloaded
- The download finishes
- The user is shown a UI element with the option to install the update
autoUpdater.checkForUpdates()is called again (e.g., periodically in asetInterval())- This deletes the directory of the previously downloaded update
- It starts downloading the new version
- However, the path of the previously downloaded update is still referenced in
ShipItState.plist - The user clicks on "Update & Restart" in the UI before the new download is complete
autoUpdater.quitAndInstall()is called- It reads the path of the previously downloaded update from
ShipItState.plistand tries to install it - The update fails because the directory no longer exists (inside of
prepareAndValidateUpdateBundleURLForRequest, link 1, link 2) - The app does not relaunch
This race condition is also not as rare as it might seem. Electron apps can easily reach 500MB or more. On a slow connection, that download can take a few minutes. If the user decides to update at any point during those few minutes, this bug will occur.
IMPORTANT: It is not safe to delete old ShipIt directories! They might still be referenced by ShipItState.plist or a download to those directories might be in progress and they will be referenced by ShipItState.plist once that download completes. Deleting them leaves us with a broken Squirrel.Mac state!
Another problem is that #49365 was a feature labeled as a bug fix and was thus backported to older release branches without WG Releases approval in violation of our normal processes. We have to be very careful with the auto updater, and I'm fairly certain these backports would not have been approved had they been properly marked as a feature.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status