# Troubleshooting This page will attempt to help you to determine the cause of a problem with Firefox Application Update. This is both geared towards both Mozilla employees triaging incoming Application Update bugs and towards users who want to figure out for themselves why they are experiencing problems and how they might fix them. In order to make things a bit easier for employees doing triage, some sets of troubleshooting steps will be formatted as code blocks to make it easier to copy and paste them into a bug comment. In general, the first step of the troubleshooting process is going to be figuring out which stage of the update process is causing problems. This is easiest with a solid understanding of the [implementation of the update system](Implementation.md). Then you can figure out how far through the update process we are making it successfully. With this knowledge, we can figure out the correct logs to collect. If you are unsure, start by collecting the Browser Console logs. ## Error Lookup It is very common during troubleshooting to see errors in the status file or in log messages. Since these errors are numeric, we need to translate them into something more useful. This can be done using `toolkit/mozapps/update/common/updatererrors.h`. ## Log File Analysis Let's will walk through logs for a successful update of a copy of Firefox Nightly for Windows in order to give a sense of what things are meant to look like. ### Browser Console Logs Browser console logs help us find problems that happened when downloading the update and preparing it for the update binary. They can be collected like this: ``` 1. Navigate to `about:config`. 2. Set `app.update.log` to `true`. 3. Open the Browser Console either with the hotkey Control+Shift+J (Command+Shift+J on macOS), or via Hamburger Menu (☰) -> More Tools -> Browser Console 4. In the Filter textbox at the top, enter `AUS:` to filter out everything except the update messages. 5. Navigate to the "Update" section of `about:preferences`. It should automatically check for an update. 6. Once the update check has completed, copy the messages out of the Browser Console and attach them to this bug. ``` We'll go through some things to look for when reading a browser console log. It can be good to read through the initial status information: ``` AUS:SVC Logging current UpdateService status: AUS:SVC UpdateService.canUsuallyCheckForUpdates - able to check for updates AUS:SVC UpdateService.canCheckForUpdates - able to check for updates AUS:SVC getCanApplyUpdates - testing write access C:\ProgramData\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38\updates\6F193CCC56814779\update.test AUS:SVC getCanApplyUpdates - bypass the write since elevation can be used on macOS and Windows AUS:SVC isServiceInstalled - returning true AUS:SVC shouldUseService - returning true AUS:SVC getCanStageUpdates - able to stage updates using the service AUS:SVC Elevation required: false AUS:SVC Other instance of the application currently running: false ``` It looks like we are able to check for, apply, and stage updates. It also looks like we can use the Mozilla Maintenance Service. Note that the line saying that `Elevation required: false` is performing a macOS-only check. Also, the fact that no other instances of the application are currently running is important since they [will interfere with the update process](Concepts.md#update-mutex-and-update-sync-manager). After this, we should find log lines telling us whether Firefox started with an existing `downloadingUpdate` or `readyUpdate`. In this case, we did not. ``` AUS:SVC UpdateManager:#reload - Reloaded downloadingUpdate as null AUS:SVC UpdateManager:#reload - Reloaded readyUpdate as null ``` We can also see what the initial value of `update.status` was. ``` AUS:SVC UpdateService:#asyncInit - status = "null" ``` It may be useful to trace the entire `#asyncInit` flow to get a sense of what the overall state is after initialization. In this example, the only other initialization is ``` AUS:SVC UpdateService:#asyncInit - Resetting update state ``` This means that Firefox will not use any state from previous update attempts. It is going to start fresh. Now we will observe the update check being made. ``` AUS:SVC CheckerService:#updateCheck - sending request to: https://aus5.mozilla.org/update/6/Firefox/148.0a1/20251209143057/WINNT_x86_64-msvc-x64/en-US/nightly/Windows_NT%252010.0.0.0.26100.7171%2520(x64)/ISET%3ASSE4_2%2CMEM%3A32213/default/default/update.xml?force=1 ``` At the time of writing this, pasting this URL into the browser yields this XML: ```XML ``` Given this, we can determine that the result of this update check ought to be a single update with two possible patches. Next we see that Firefox is going to try to download this update. ``` AUS:SVC Creating Downloader AUS:SVC Downloader:downloadUpdate AUS:SVC Downloader:_selectPatch - Patch selected. Assigning update to downloadingUpdate. AUS:SVC getCanUseBits - BITS can be used to download updates AUS:SVC Downloader:_canUseBits - Patch is able to use BITS download AUS:SVC Downloader:_maybeWithExtras - Adding extras AUS:SVC UpdateService:makeBitsRequest - Starting BITS download with url: https://archive.mozilla.org/pub/firefox/nightly/partials/2025/12/2025-12-10-09-56-35-mozilla-central/firefox-mozilla-central-148.0a1-win64-en-US-20251209143057-20251210095635.partial.mar?backgroundTaskMode=0, updateDir: C:\ProgramData\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38\updates\6F193CCC56814779\updates\downloading, filename: update.mar AUS:SVC Downloader:downloadUpdate - BITS download running. BITS ID: {56F3868B-4CE2-40A5-8937-A3AA44D33D3F} ``` It looks like Firefox is going to use [BITS](Concepts.md#bits) to download this update. If we wanted to, we could open Powershell while this download was in-progress and run `Get-BitsTransfer -JobId "{56F3868B-4CE2-40A5-8937-A3AA44D33D3F}"` to investigate the status of the transfer. Next, we see a [state change](Concepts.md#update-state): ``` AUS:SVC writeStatusFile - status: downloading, path: C:\ProgramData\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38\updates\6F193CCC56814779\updates\0\update.status AUS:SVC onStateAccessSuccess AUS:SVC Downloader:downloadUpdate - Set status to downloading AUS:SVC Downloader:downloadUpdate - Setting state to downloading AUS:SVC Downloader:downloadUpdate - setting currentState to STATE_DOWNLOADING AUS:SVC transitionState - "STATE_IDLE" -> "STATE_DOWNLOADING". ``` This indicates to us that Firefox believes it has successfully started downloading the update. Once we see `onStopRequest`, the download has completed. ``` AUS:SVC Downloader:onStopRequest - downloader: BITS, status: 0 AUS:SVC Downloader:onStopRequest - status: 0, current fail: 0, max fail: 10, retryTimeout: 2000 ``` The `0` status indicates that the download completed successfully. Great! Let's see what state we transition to from here: ``` AUS:SVC Downloader:onStopRequest - Clearing readyUpdate in preparation of moving downloadingUpdate into readyUpdate. AUS:SVC isServiceInstalled - returning true AUS:SVC shouldUseService - returning true AUS:SVC isServiceInstalled - returning true AUS:SVC shouldUseService - returning true AUS:SVC getCanStageUpdates - able to stage updates using the service AUS:SVC Downloader:onStopRequest - Ready to apply. Setting state to "pending-service". AUS:SVC writeStatusFile - status: pending-service, path: C:\ProgramData\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38\updates\6F193CCC56814779\updates\0\update.status AUS:SVC onStateAccessSuccess AUS:SVC Downloader:onStopRequest - Setting bitsResult to 0 AUS:SVC Downloader:onStopRequest - setting state to: pending-service AUS:SVC Downloader:onStopRequest - Moving downloadingUpdate into readyUpdate AUS:AUM AppUpdater:#awaitDownloadComplete.observer.onStopRequest - aRequest: [xpconnect wrapped nsIRequest], aStatusCode: 0 ... AUS:SVC transitionState - "STATE_DOWNLOADING" -> "STATE_STAGING". ``` Since we got `pending-service` and `STATE_STAGING` next, it looks like we can use the Maintenance Service to [stage the update](Concepts.md#staging). ``` AUS:SVC UpdateManager:refreshUpdateStatus - Staging done. AUS:SVC readStatusFile - status: applied, path: C:\ProgramData\Mozilla-1de4eec8-1241-4177-a864-e594e8d1fb38\updates\6F193CCC56814779\updates\0\update.status AUS:SVC UpdateManager:refreshUpdateStatus - status = applied ``` `refreshUpdateStatus` is called when staging is complete. And the `applied` status indicates that it completed successfully. ``` AUS:SVC isServiceInstalled - returning true AUS:SVC shouldUseService - returning true AUS:SVC UpdateManager:refreshUpdateStatus - Staging successful. Setting status to "applied-service" ... AUS:SVC transitionState - "STATE_STAGING" -> "STATE_PENDING". ``` We are able to use the Maintenance Service for the last bit of the installation: the replace request, so we set the status to `applied-service`. Since we are now ready to restart to update, the AUS state is set to `STATE_PENDING`. At this point, Firefox is ready to restart to install the update. ### Update Binary Logs Update binary logs can help find problems that occurred during the actual installation of an update. They can be collected like this: ``` 1. Navigate to `about:support` 2. Find the "Update Folder" entry and click "Open Folder". 3. Open the `updates` directory. 4. Inside, you should find some `.log` files: `last-update.log`, `last-update-elevated.log`, `backup-update.log`, `backup-update-elevated.log`. They may not all exist. Please attach whichever ones do exist to this bug. ``` When the update binary runs, it initially logs to `updates/0/update.log`. If it needs to invoke a [second updater](Implementation.md#update-binary) for elevation, that log will end up at `updates/0/update-elevated.log`. When Firefox runs and analyzes the results of the update, it will move these logs to `updates/last-update.log` and `updates/last-update-elevated.log`, respectively. If those files already exist, they are moved to `updates/backup-update.log` and `updates/backup-update-elevated.log`, respectively. Since most people check for logs after restarting Firefox to update and since staging is enabled by default, it is common that the `backup-update` logs contain the log messages from staging and the `last-update` logs contain the log messages from the actual installation. Note that lines in the update logs are prefixed with timestamps. This can be helpful to find out if the update stalled somewhere. But it is also worth taking note of them just to make sure that the timing makes sense. Make sure that, for example, if the bug reporter says that this problem happened yesterday, that the logs aren't from months ago. This could point towards the problem happening in Firefox rather than in the update binary. If you see this, take another look at the browser console logs. #### Backup Update Log Let's look at `backup-update.log` first. Updater logs should generally have a section like this early on that does a good job of describing the way that the updater was invoked: ``` 2025-12-10 09:13:47-0800: sUsingService=false 2025-12-10 09:13:47-0800: sUpdateSilently=false 2025-12-10 09:13:47-0800: useService=true 2025-12-10 09:13:47-0800: isElevated=false 2025-12-10 09:13:47-0800: gInvocation=UpdaterInvocation::First ``` From this we can tell that we are allowed to use the Maintenance Service, but are not using it yet. The updater does not appear to have elevation, which makes sense given that this is the first invocation; we have not yet started the elevated copy of the updater. ``` 2025-12-10 09:13:47-0800: Performing a staged update ``` This confirms that `backup-update.log` describes the staging process. ``` 2025-12-10 09:13:47-0800: Checking whether elevation is needed 2025-12-10 09:13:47-0800: Failed to open update lock file: 5 2025-12-10 09:13:47-0800: Can't open lock file - seems like we need elevation 2025-12-10 09:13:47-0800: After checking IsProgramFilesPath, useService=true 2025-12-10 09:13:47-0800: After checking IsLocalFile, useService=true 2025-12-10 09:13:47-0800: After checking IsUnpromptedElevation, useService=true 2025-12-10 09:13:47-0800: Writing status to file: failed: 58 ``` Since we couldn't open the update lock file, the updater needs elevation. The checks afterwards show that there is nothing stopping us from using the Maintenance Service. We then see what looks like an error. But if we [look it up](#error-lookup), we see that `58` corresponds to `SERVICE_UPDATE_STATUS_UNCHANGED`. This is normal; we set this status as part of our error detection that the elevated updater process worked properly. ``` 2025-12-10 09:13:47-0800: Launched service successfully 2025-12-10 09:13:56-0800: Service stop detected. 2025-12-10 09:13:56-0800: Not showing a UAC prompt. 2025-12-10 09:13:56-0800: useService=true ``` This indicates that we launched the service and it ran successfully. #### Backup Update Elevated Log Next, let's look at the `backup-update-elevated.log` that pairs with the above log. This should be the elevated portion of the staging from that process. ``` 2025-12-10 09:13:47-0800: sUsingService=true 2025-12-10 09:13:47-0800: sUpdateSilently=false 2025-12-10 09:13:47-0800: useService=false 2025-12-10 09:13:47-0800: isElevated=true 2025-12-10 09:13:47-0800: gInvocation=UpdaterInvocation::Second ``` This looks expected. We are using the service on our second invocation of the updater. ``` 2025-12-10 09:13:47-0800: Going to update via this updater instance. ``` Great! We are going to do the actual staging now. This should be followed by many `PREPARE` statements, then many `EXECUTE` statements, then many `FINISH` statements showing the progress of the update. Look through these for any "failed" messages indicating a failure of the update process. If there is one, we should immediately move to the `FINISH` phase which, in this case, will involve rolling the installation back to its original state. ``` 2025-12-10 09:13:55-0800: succeeded 2025-12-10 09:13:55-0800: Writing status to file: applied ``` Here we see that the update was successful and we updated the status file accordingly. This matches what we saw in the browser console log. ``` 2025-12-10 09:13:55-0800: Running LaunchCallbackAndPostProcessApps 2025-12-10 09:13:55-0800: No callback arg. Skipping LaunchWinPostProcess and LaunchCallbackApp ``` We didn't re-launch Firefox after the update. Which is expected when staging. #### Last Update Log Now we are going to look at a `last-update.log` where we are not staging. Once again, we'll look at the block at the top to see what state we are in: ``` 2025-12-10 11:16:13-0800: sUsingService=false 2025-12-10 11:16:13-0800: sUpdateSilently=false 2025-12-10 11:16:13-0800: useService=true 2025-12-10 11:16:13-0800: isElevated=false 2025-12-10 11:16:13-0800: gInvocation=UpdaterInvocation::First ``` Note that there is no particular message to indicate an in-place update. But we can tell from the lack of `Performing a staged update` and `Performing a replace request` messages that this is an in-place update. Much of the analysis from here goes pretty much the same way it did for the [Backup Update Log](#backup-update-log). But towards the end we get this difference: ``` 2025-12-10 11:16:25-0800: Running LaunchWinPostProcess 2025-12-10 11:16:25-0800: LaunchWinPostProcess - Waiting for process to complete 2025-12-10 11:16:27-0800: LaunchWinPostProcess - Process completed ``` This means that we launched the Post Update process (described [here](Implementation.md#update-binary)) successfully. This ought to be done during an in-place update or a replace request, but not when staging. #### Last Update Elevated Log Next, let's look at the `last-update-elevated.log` that pairs with the above log. This should be the elevated portion of the staging from that process. Most of this should match closely with the [Backup Update Elevated Log](#backup-update-elevated-log) that we already looked at. But some parts towards the end will differ ``` 2025-12-10 11:16:22-0800: NS_main: unable to remove directory: tobedeleted, err: 41 2025-12-10 11:16:22-0800: NS_main: directory will be removed on OS reboot: tobedeleted ``` This is normal during an in-place update. We will still be using some parts of the installation (like the updater) that we can't delete yet. But we register them with the OS to be removed on the next boot. ``` 2025-12-10 11:16:22-0800: Running LaunchCallbackAndPostProcessApps 2025-12-10 11:16:22-0800: Launching Windows post update process 2025-12-10 11:16:22-0800: The file "C:\Program Files\Firefox Nightly\uninstall\helper.exe" is signed and the signature was verified. 2025-12-10 11:16:22-0800: LaunchWinPostProcess - Waiting for process to complete 2025-12-10 11:16:25-0800: LaunchWinPostProcess - Process completed ``` Like in the previous section, we now do the post update process, which should be completed in both the unelevated and elevated updater. ``` 2025-12-10 11:16:25-0800: Not starting service update. MMS will handle it. ``` When we update with the Maintenance Service, the Service handles updating itself. But if we update without it, we may install an update to the Service at this point. ``` 2025-12-10 11:16:25-0800: LaunchCallbackAndPostProcessApps:3237 - Returning early. This is the second updater instance. ``` We don't launch the callback from the elevated updater, we let the unelevated updater do that after this one exits. ## Common Classes of Problems ### Firefox Doesn't Update Troubleshooting this generally involves some knowledge of how the update system works. This allows us to determine where in the update process the failure is happening. Depending on where the failure is, we will probably want to ask for and analyze update logs. Potentially we may also want to look at the active update (`active-update.xml`) or the update history `updates.xml`. Especially look for [errors](#error-lookup) in the update logs that might shed light on what is going on. #### Permissions Problems A tricky variation of this problem is when the permissions of the Firefox installation directory are wrong. An example of this is [Bug 1702276](https://bugzilla.mozilla.org/show_bug.cgi?id=1702276). This will generally present as an update log that suggests that we should have the permission to update, but attempts to actually write to the files result in Windows Error 5 ([Access Denied](https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-)). A good way to check for this is to ask the reporter: ``` Run this command, substituting your install directory: `icacls ""`. For example, I would run `icacls "C:\Program Files\Firefox Nightly"`. Attach the output of this command to this bug. ``` We expect results extremely similar to these: ``` > icacls /c/Program\ Files/Firefox\ Nightly/ C:/Program Files/Firefox Nightly/ S-1-15-3-1024-1238444810-1356253261-2257478630-1143196962-1563090664-2414759320-1282101916-4218287853:(OI)(CI)(RX) NT SERVICE\TrustedInstaller:(I)(F) NT SERVICE\TrustedInstaller:(I)(CI)(IO)(F) NT AUTHORITY\SYSTEM:(I)(F) NT AUTHORITY\SYSTEM:(I)(OI)(CI)(IO)(F) BUILTIN\Administrators:(I)(F) BUILTIN\Administrators:(I)(OI)(CI)(IO)(F) BUILTIN\Users:(I)(RX) BUILTIN\Users:(I)(OI)(CI)(IO)(GR,GE) CREATOR OWNER:(I)(OI)(CI)(IO)(F) APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL APPLICATION PACKAGES:(I)(OI)(CI)(IO)(GR,GE) APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(RX) APPLICATION PACKAGE AUTHORITY\ALL RESTRICTED APPLICATION PACKAGES:(I)(OI)(CI)(IO)(GR,GE) ``` The line with the long user ID should be expected to have a different user ID. Other than that, almost any variation from this is a sign for concern. [The documentation](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/icacls#remarks) can help decode this output to figure out what it means. The permissions that will be most important here are `BUILTIN\Users`, which likely corresponds to the permissions that users have without elevation, `BUILTIN\Administrators`, which corresponds to the permissions that users have with UAC elevation, and `SYSTEM`, which corresponds to the permissions that the Mozilla Maintenance Service has. ### Unexpected UAC Prompts / Mozilla Maintenance Service isn't Working A common reported problem is that update works successfully on Windows, but requires a User Account Control (UAC) prompt. This means that the [Mozilla Maintenance Service](Implementation.md#mozilla-maintenance-service) isn't working properly. The reason that this would happen could lie in the browser console log or the update binary log. Either the browser console log will indicate that it didn't set `applied-service` or `pending-service` or the update binary log will indicate `useService=false` somewhere. This should provide leads for why the Mozilla Maintenance Service isn't being used. ### Firefox Forces a Restart These are very likely duplicates of [Bug 1480452](https://bugzilla.mozilla.org/show_bug.cgi?id=1480452), but we generally want to be sure about this. We want to know if there is a new mechanism that can cause this problem. Occasionally, this is instead something like [Bug 1892995](https://bugzilla.mozilla.org/show_bug.cgi?id=1892995). In that example, enterprise software is requesting us to open `about:restartrequired` in order to encourage the user restart. But the browser actually continues working since it has not actually been updated. There is another example that we haven't seen in some time where external software actually does update Firefox while it is running, causing the page to be shown accurately. Nonetheless, this type of bug is INVALID since there isn't really anything we can do to fix this. If some other program deletes our files while Firefox is running, this is the inevitable result. This problem can be uncovered by asking for the update history (`updates.xml`) to see if Firefox is actually installing the problematic updates. ### Channel Changes or Version Downgrades We go to a rather large amount of effort to prevent channel changes and version downgrades. We check at multiple stages of the update process that we aren't doing this. If a user reports this, ask them for a list of enterprise software that is running on their machine. It typically turns out that some piece of enterprise software is trying to force Firefox to some particular version and it is at fault, not Firefox. Another direction for troubleshooting this is to check the update history (`updates.xml`). If no entries in the history match these updates, Firefox probably isn't performing them. We cannot generally do anything about this from within Firefox, so these are generally resolved as INVALID. ## Other Useful Copy/Pastes for Bugzilla For when having a problem specifically with the Maintenance Service itself. Note that these problems are very unusual. You should check that we are actually trying to invoke it first. ``` The most recent Maintenance Service logs should be located at `C:\Program Files (x86)\Mozilla Maintenance Service\logs\maintenanceservice.log`. Please attach that file to this bug. ``` Occasionally, it is useful to ask the bug reporter to run code in the browser console. In which case this may be useful. ``` Enable running commands in the Browser Console by navigating to `about:config` and setting `devtools.chrome.enabled` to `true`. ```