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. 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.
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:
<updates>
<update type="minor" displayVersion="148.0a1" appVersion="148.0a1"
platformVersion="148.0a1" buildID="20251210095635">
<patch type="complete"
URL="https://archive.mozilla.org/pub/firefox/nightly/2025/12/2025-12-10-09-56-35-mozilla-central/firefox-148.0a1.en-US.win64.complete.mar"
hashFunction="sha512"
hashValue="0234e8875cd12eb0f87dc76709a4869043082efbe5067f1fae138517e5c5a524ab6013c7331526f86322c19acefa4a04ba4d7edda05608233294bdef3867dd46"
size="94587463"/>
<patch type="partial"
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"
hashFunction="sha512"
hashValue="6d98fb6934274ce5cd6a6f22ee50145d889e9d59d2989f9633f26fef6cd0817f3f9bd0d5e3da3a81bd93ef8ca05754ee50a568f2c364f011093cfd348b061405"
size="10738378"/>
</update>
</updates>
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 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:
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.
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 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, 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. 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) 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 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 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. 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). A good way to check for this is to ask the reporter:
Run this command, substituting your install directory: `icacls "<installdir>"`. 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
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
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, 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. 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`.