Reading view

There are new articles available, click to refresh the page.

Why the macOS 26.4 update appears to freeze

Many discovered how long 5 minutes could last when they updated from macOS 26.3.1 to 26.4. Right at the end of its Preparation phase, Software Update showed there were only 5 minutes remaining for far longer. This article reveals what went wrong with that update.

My observations come from a Mac mini M4 Pro running a vanilla installation of macOS Tahoe, being updated from 26.3.1 (a) with the BSI installed, to 26.4. Times and details are taken from log extracts covering the final 14 minutes of the update, immediately prior to the reboot for its installation.

Preparation

At almost exactly 18:43:00, softwareupdated reported that the PREPARING_UPDATE phase was in progress, with 70% complete on the progress bar, and 20 minutes remaining. Periodic preparation activities were then reported in the log, mainly verifying components to be installed as part of the update. One of the longest of those, /usr/standalone/i386/Firmware.scap, took nearly 6.5 minutes alone, although you might wonder why that’s required on an Apple silicon Mac!

Eleven seconds later, softwareupdated changed the progress bar to display 10 minutes remaining, with 71% completed. Just 1.5 seconds later that changed again to display 5 minutes remaining with 94% complete. Six seconds after that, with 5 minutes still displayed, the log records 98.6% was complete.

The log and progress bar then remained stuck at 5 minutes remaining and 98.6% complete for the next 11 minutes and 47 seconds, before changing to 99.9% complete and no time remaining.

These are plotted in the chart below.

The final 5 minute period started at 18:43:12, and lasted until 18:55:04, as reflected in the long period of 98.6% completion (upper line) and 5 minutes remaining (lower line).

The “5 minutes” remaining actually took 12 minutes and 7 seconds, although log entries make it clear that preparation continued throughout that time, with further verifications and “Preparing system volume…”. Those details were reported as ActionText for progress monitoring, but curiously aren’t accessible to the user at the time.

Log entries record softwareupdated keeping detailed records of progress over this period, though. For example:
18:51:32.924688 softwareupdated PrepareUpdate PROGRESS (Continue) | state:{
ActionText = "Preparing system volume...";
ElapsedTime = 490;
ExpectedTime = 1335505;
PercentBytesComplete = "48.05373989419242";
PercentComplete = "4.701870471432042";
}

But those aren’t reflected in the progress bar.

Once the update had completed that preparation phase, extensive checks were performed to ensure it was correctly configured, and components were moved into place in the ‘stash’ to be used during installation. One second after successful completion, softwareupdated locked the controller state and waited for the reboot to start installation. Rebooting followed less than two minutes later.

What went wrong?

The macOS 26.4 update for Apple silicon Macs was large, and the work required to verify its contents and complete its preparation was incorrectly reported in both percent completion and time remaining. Even in smaller updates, some form of progress needs to be shown in the progress bar during these later stages of preparation, or users may be mislead into thinking the update has frozen or failed, and could for example restart their Mac to try updating again.

What should the user do?

When an update claims there’s only 5 minutes left, that could readily extend to longer, possibly on slower Macs as long as 30 minutes or more. Unless there’s evidence that the update has gone wrong at this stage, you should leave your Mac to complete it, as it almost certainly will. If you’re still in doubt and want to confirm that the update hasn’t frozen, open Activity Monitor and look for around 100% CPU from softwareupdated or related processes, and disk activity.

Unfortunately, there’s nothing the user can do to accelerate macOS updates.

Last Week on My Mac: Update progress

One of the longstanding jokes in computing is how misleading progress indicators can be, and last week most of us had a timely reminder when we updated macOS. However much we might like a perfectly accurate linear indicator for macOS updates, this is one of those situations where the best we can expect is a compromise, as I tried to explain here.

Showing progress

There are two types of progress indicator, determinate and indeterminate, depending on whether the task is quantifiable and progress is measurable. Determinate indicators are always preferred, as they inform the user whether they need only wait only a few moments, or they have time to enjoy a leisurely meal, but that requires quantifiability and measurability.

The simple example is copying a file from one disk to another: although macOS doesn’t know in advance how long that might take, it can quantify the task as the size of the file to be copied, then keep track of how much of that has already been completed. When half the size of the file has been copied, the progress bar can be set to half-way along its total length, so providing an accurate indication of progress.

However, with some copy operations that breaks down: when copying a sparse file between APFS volumes, for example, only the sparse data is copied, not the whole file size. As a result, copying sparse files often results in progress bars that jump from a low point to completion in the twinkling of an eye. This also relies on the quantities involved being linearly proportional to the time required, an assumption that often breaks down when downloading from a remote server.

macOS updates

Updating macOS consists of a series of many tasks (see references at the end), of which only one, downloading, is both quantifiable and has measurable progress, and even that may be far from linear. Apple therefore has a choice of:

  • Display multiple progress indicators, appropriate to each phase. While that might work well for the download phase, it can’t work for others, including preparation, which is likely to take a period of several minutes at least.
  • Combine those into a single progress bar, as at present.
  • Use an indeterminate progress indicator, such as a spinning wheel, which would be reliable but unhelpful.

As downloading is the one task that is quantifiable and its progress is measurable, I’ll start there.

For this, the progress bar starts an an arbitrary 15%, and softwareupdated assumes the total size of that download is the magnitude of that task.

When the download has been completed, the progress bar reaches an arbitrary 55%, and its caption then changes to reporting progress with preparation.

There is a weakness in the assumption that becomes obvious when downloading from a local Content Caching server, as the final 1 GB or so normally isn’t provided from the cache, but has to be freshly downloaded from Apple’s servers. However, that isn’t normally apparent when caching isn’t available and the whole of the download comes from the same remote source.

For the remainder of the progress bar, between 0%-15% and 55%-100%, the task is neither quantifiable nor measurable. Instead, softwareupdated divides it into a series of subtasks, each of which has a fixed progress level. One list of subtasks and levels obtained from the log is given in the Appendix at the end.

The disadvantage of that strategy is that time required by each subtask varies with the update and the Mac being updated. Inevitably, computationally intensive subtasks will proceed more rapidly on newer and faster Macs, while those mainly constrained by disk speed should be more uniform. Large updates should take significantly longer, and that will vary by subtask as well.

The last 5 minutes

A particular problem with some more recent macOS updates, including that from 26.3.1 to 26.4 last week, has been unmarked progress over the final “5 minutes” of preparation. While indeterminate progress indicators continue to move over that period, and reassure the user that the task hasn’t ground to a halt or frozen, the progress bar shown had no intermediate points, making it easy to misinterpret as failure to progress. If this is going to be a feature of future macOS updates, Apple needs to insert some intermediate points to let the user know that the update is still proceeding.

Conclusion

A progress bar that combines different measures of progress, such as download size and substages, can work well, but only if the user is aware of how to read it. As we only update macOS a few times each year, that isn’t sufficient exposure, and how it works needs to be made explicit.

Previously

How macOS 26 Tahoe updates 1
How macOS 26 Tahoe updates: 2 Finite state machines
How macOS 26 Tahoe updates: 3 Catalogues and preparing to download
How macOS 26 Tahoe updates: 4 Download, preparation and installation
Read the macOS update progress bar

Appendix

Progress bar percentages set for some subtasks during updating macOS 26.2 to 26.3 on an Apple silicon Mac:

  • 000.1 ACCEPTED
  • 000.2 STARTUP
  • 000.3 LOADING_PERSISTED
  • 000.5 PURGING
  • 000.6 CANCEL_SUCORE
  • 000.7 CANCEL_MSU
  • 000.8 CANCEL_STATE
  • 000.9 READY
  • 001.0 RELOADING_SU
  • 002.0 RELOADING_ROSETTA
  • 003.0 RELOADING_UPDATE_BRAIN
  • 004.0 DOWNLOADING_UPDATE_BRAIN
  • 007.0 PREFLIGHT_WAKEUP
  • 009.0 PREFLIGHT_PREREQUISITE
  • 010.0 PREFLIGHT_PERSONALIZE
  • 015.0 DOWNLOADING_ROSETTA
  • 016.0 DOWNLOADING_UPDATE
  • 054.0 DOWNLOADED_UPDATE
  • 055.0 PREFLIGHT_FDR_RECOVERY
  • 060.0 PREPARING_UPDATE
  • 099.0 PREPARED
  • 100.0 COMPLETED

Note the majority of the progress period (79%) is assigned to downloading (15%-55%) and preparing (60%-99%).

How macOS 26 Tahoe updates: 4 Download, preparation and installation

In my account of how Tahoe updates macOS, I had reached the stage when Rosetta and the main update had started downloading from Pallas, Apple’s software update server (see the Appendix at the end for further explanation of terms used).

Download

Currently, the main update download (at least) is compressed using Zip, and is decompressed as a stream during download, so there’s no delay decompressing during the preparation phase later.

In this case, downloading the main update was completed within 8 minutes. The source of the Zip archive was originally given as a path on [https://]updates.cdn-apple.com/2026WinterFCS/patches, and that was written to a local path on /System/Library/AssetsV2/com_apple_MobileAsset_MacSoftwareUpdate/ In my case, though, I have a local Content Caching Server running, and immediately before the download started com.apple.AssetCacheServices substituted a download URL on that server to ensure the update was obtained through the local caching server. At the same time, an Event Report was sent back to Apple, recording the start of download.

Progress was updated every second during the download, and brought the progress bar from 16% to 53.9% over the following 8 minutes, with little other activity taking place.

Preflight

Activity then changed to what is repeatedly referred to as Preflight FDR Recovery, and is the first entry point for the UpdateBrainService, downloaded for MobileSoftwareUpdate rather than softwareupdated.

This runs an Event Recorder and begins to perform preflight checks to “recover FDR SFR”, and to perform a “firmware-only update”. To prepare for that, it retrieves various nonces and their digests for LocalPolicy, RecoveryOS boot policy, and others. Following those is the first of many attempts to determine purgeable space, in preparation for installation of the update. Those are performed by com.apple.cache_delete.

Pallas was then checked to see if there was any more recent version of RecoveryOS UpdateBrain, but there wasn’t. A further check for any newer recoveryOS was also made, before the main macOS update was prepared, at a progress level of 60% as set previously.

Preparation

The first step of the main preparation phase is to purge staged assets with com.apple.cache_delete. With that complete, UpdateBrainService recalculates cryptex size requirement for the update, and the install target prepare size:

  • cryptex size is 1.2 times the app cryptex size = 60 MB, plus 1.2 times the system cryptex size = 7749 MB, a total of 7809 MB, as previously calculated;
  • prepare size is the sum of the snapshot installation size of 3785 MB, the cryptex size of 7809 MB, three ‘slack sizes’ for VW, Recovery and Preboot of 2048 + 1024 + 1024 = 4096 MB, the new template size of 991 MB, twice the update partition size totalling 600 MB, less the old template size of 363 MB. The grand total comes to 16,918 MB.

UpdateBrainService then checks volume free sizes, and confirms that they’re sufficient to complete the update. It next creates a ‘stash’, which is protected by keys in the stash keybag, handled by the Secure Enclave Processor. There is then another round of purging with com.apple.cache_delete.

Much of the preparation phase is spent verifying the protection of installation packages, cryptexes, then the contents of /System/Applications and /System/Library. As progress is about 64% complete, System volume preparations are started, and there’s another round of purging by com.apple.cache_delete. There’s surprisingly little log activity as progress passes 70% complete.

With progress reaching 84% complete, UpdateBrainService starts unarchiving files in parallel, taking just under 5 seconds to complete those. Following that, there’s another brief period unarchiving data files in parallel, then working with the contents of /System/Volumes/Update/mnt1/private/var/MobileAsset/PreinstalledAssetsV2 as progress reaches 87% complete.

When there’s 87.5% completed, UpdateBrainService reports it’s creating hard links in parallel, then is searching for new paths and verifying files, such as those in the Ruby framework. The Recovery volume is unmounted, and there’s yet another purge with com.apple.cache_delete. After those, key volume locations are checked.

The high water mark of disk usage during update is prepared. This reveals some of the steps to be undertaken during installation, including:

  • prepare source package,
  • patch cryptexes,
  • patch system volume,
  • extract to system volume,
  • install personalised.

There’s a further round of purging with cache_delete before declaring PrepareUpdate as successful, then suspending the update briefly. When update resumes, the Update volume is mounted and prepared, and there’s another round of purging. The System volume is then mounted, checked, and prepared. Progress is now at 98.5% complete, and once 100% is reached, the countdown to restarting the Mac is begun.

Installation

During the download and preparation phases, apart from repeated purging, the log is generally quiet. This changes dramatically once the Mac starts preparing for shutdown and installation. WebKit is cleaned up and shut down, as are many other processes. The ‘stash’ of update components is then committed, and final scans and checks are completed.

The update is then applied, followed by Rosetta, RecoveryOS, UpdateBrain and finally minor documentation. After that period of nearly 20 seconds, this phase is declared complete, and a restart is notified before waiting for the essential reboot.

Reboot

Once rebooting by root has been initiated, the boot chime is muted to ensure the update continues in silence. The last log message is written a few seconds later, and UpdateBrain then runs the update.

Less than 3 minutes later, the system boot is recorded in the log, and kprintf is initialised 5 seconds later. About 3 minutes afterwards softwareupdated is started up, and runs various clean-up routines to complete the update sequence in conjunction with ControllerSetup and a Finite State Machine.

Key points

  • The main update download is decompressed while streaming, to save preparation time later.
  • If a local Content Caching Server is connected, AssetCacheServices will substitute its IP address for that of the Pallas server to ensure the download is obtained through the cache.
  • Following download, extensive preflight checks are performed.
  • During preparation components are verified, paths checked, and some unarchiving is performed.
  • Prior to reboot and installation, processes including WebKit are shut down in readiness for reboot and install.
  • The boot chime is muted.
  • Once rebooted, clean-up is performed.

Previously

How macOS 26 Tahoe updates 1
How macOS 26 Tahoe updates: 2 Finite state machines
How macOS 26 Tahoe updates: 3 Catalogues and preparing to download

Appendix: Terms used

  • FDR is unknown, but appears associated almost exclusively with a preflight phase.
  • Pallas is the internal name for Apple’s software update server. This appears throughout log entries, where for example Pallas audience is jargon for the type of user, normally macOS Customer.
  • RecoveryOS appears to refer to the version of Recovery in the hidden container of the internal SSD, more widely known as Fallback Recovery.
  • SFR appears to refer to the version of Recovery in the Recovery volume of the active boot volume group, also known as Paired Recovery.
  • Splat, semi-splat and rollback objects all refer to cryptexes. Splat is the general term, while semi-splat refers to a cryptex-based update that might include rapid security responses (RSR) and background security improvements (BSI) implemented by replacing one or both cryptexes. Rollback objects are older versions of a cryptex that have been saved to allow a newer cryptex to be reverted to that older one, in the event that the newer cryptex causes problems.
  • UpdateBrain is the executable code supplied as part of an update that prepares and installs that specific update. There’s a separate UpdateBrainService for RecoveryOS.

How macOS 26 Tahoe updates: 3 Catalogues and preparing to download

Following a general outline of what happens during a macOS 26 update, and a more detailed account of how it uses finite state machines and sends progress reports to Apple, this article describes what happens before Software Update downloads the main update. This was started by opening Software Update in System Settings of macOS 26.2 when the update to 26.3 was available, on a Mac mini M4 Pro. The Appendix at the end explains several in-house jargon terms used widely through these log entries.

Check for an update

In this case, checking for an update was instigated by opening Software Update in System Settings. That initiated a series of preliminary checks to:

  • determine whether that Mac and user are enrolled in a beta-test programme;
  • obtain the Pallas audience, in this case macOS Customer;
  • determine the time interval since the last scan for updates, and its result. As that was 632.8 seconds ago and there were no updates reported as being available then, a further scan is deemed acceptable;
  • set the base URL for Pallas of mesu.apple.com/assets/macos/.

A new scan for updates is started, with a UUID chosen to identify it. The UUID used is version 5, so is expected to be based on a hash of other identifiers, and is unique to this software update. The catalogue is downloaded from Pallas, and analysed for new versions being offered for download.

In this case there are two available:

  • macOS263Short comes with just an arm64e system cryptex at 6,458 MB, and a download size of 3.68 GB which unarchives to 4.36 GB;
  • macOS263Long comes with both arm64e and x86_64 system cryptexes at 6,458 + 2,312 MB, and a download size of 17.48 GB which unarchives to 18.14 GB.

Both of those use the Zip compression algorithm, and are designated as being ZipStreamable. macOS263Short is clearly the Delta update from 26.2, whose download size was then displayed in the Software Update panel. macOS263Long appears to be a full upgrade, equivalent to the macOS Installer app in terms of its contents.

A similar sequence of events occurs when you request a list of available macOS installers using the command
softwareupdate --list-full-installers

Routine checks

The following checks are repeated at frequent intervals throughout scanning and preparation:

  • the presence of rollback objects, a rollback copy of cryptex1 in the Preboot volume;
  • whether semi-splat is active, by comparing the Splat RestoreVersion with the Cryptex1 RestoreVersion;
  • whether the root volume is sealed;
  • whether this is an emergency update;
  • battery level, even in Macs without a battery.

Sizing

Early estimates are made of the size required to prepare and apply the update. Prepare size consists of:

  • a cryptex size requirement, consisting of the sum of the sizes of the app and system cryptexes, multiplied by 1.2, in this case a total of 7,809 MB;
  • a snapshot prepare size, consisting of the snapshot installation size of 3,785 MB plus the cryptex size, for a total of 11,595 MB.

These total 11,595 MB when first calculated, but a little later the snapshot installation size was increased to 5,154, for a total of 12,963 MB.

The apply and reserve size consists of twice the update partition size plus the update APFS reserve of 700 MB, plus 231 MiB for volume sealing overhead, giving a total of 931 MB. Presumably any shortfall in free space available would be notified to the user at this stage, and the update cancelled.

The policy for updates is determined in detail, before Pallas is asked for a catalogue of MacSplatSoftwareUpdate, updates using cryptexes, probably including both older RSRs and their successor BSIs. In this case, that catalogue is empty.

Mobile asset catalogues

softwareupdated then takes a back seat for much of the following 15 seconds or so, as mobileassetd determines which mobile assets need to be updated. These are the multitude of components to support Siri, AI and other features. This too is run by a finite state machine, AutoControlManager, which downloads catalogues of these components to assemble its auto-stager. One catalogue alone lists 91 available for update, but thankfully many of those don’t need to be updated.

Once that’s complete, the progress bar is displayed and updated by softwareupdated.

Progress bar

This is divided into zones used for different stages of progress by softwareupdated. These can be summarised as:

  • 0.0-0.9 prepare
  • 1.0-7.0 reloading and downloading Update Brain
  • 7.0-15.0 preflight
  • 15.0-55.0 downloading
  • 55.0-60.0 preflight FDR Recovery
  • 60.0-100.0 preparing update

During the downloading and preparing stages, progress updates are made according to the amount of the stage that has been completed. Otherwise they are made when each stage has been achieved.

In practice, progress is most meaningful during the downloading and preparing stages, between percentages of 15-55 and 60-100. Time estimates are displayed for both of those separately, with download time remaining based on size transferred. Once downloading is complete, the final 40% of the bar is given a fixed period of 30 minutes to complete, although that’s never required now.

Initial preparation

softwareupdated determines and downloads the cryptex updates, any SFR software update, any Rosetta update, any RecoveryOS update and the RecoveryOS update ‘brain’ for that. These are set up with their own finite state machine that downloads the catalogue, determines what should be downloaded, and downloads it. The final phase handles the documentation for the update, in this case consisting of

  • release notes summary, 1,268 B
  • release notes, 1,243 B
  • licence agreement, 97,187 B.

There’s an irony here that the first two are so tiny by comparison with the last.

In this case, downloading the update was completed within 10 minutes of obtaining the first update catalogue from Pallas.

Summary

  • After preliminary checks on beta enrolment and the period since last check, a catalogue of available updates is obtained from the software update server.
  • That catalogue offers a short Delta update, and a long full update.
  • Downloaded updates are compressed using Zip, and decompressed as they are streamed in the download.
  • Sizes required for preparation and applying the update are checked and adjusted.
  • mobileassetd determines a potentially long list of mobile assets to be updated.
  • Progress is displayed according to a combination of downloading between 15-55%, and preparation between 60-100%. Other stages are defined by progress through required steps rather than time.

Appendix: Terms used

  • Pallas is the internal name for Apple’s software update server. This appears throughout log entries, where for example Pallas audience is jargon for the type of user, normally macOS Customer.
  • RecoveryOS appears to refer to the version of Recovery in the hidden container of the internal SSD, more widely known as Fallback Recovery.
  • SFR appears to refer to the version of Recovery in the Recovery volume of the active boot volume group, also known as Paired Recovery.
  • Splat, semi-splat and rollback objects all refer to cryptexes. Splat is the general term, while semi-splat refers to a cryptex-based update that might include rapid security responses (RSR) and background security improvements (BSI) implemented by replacing one or both cryptexes. Rollback objects are older versions of a cryptex that have been saved to allow a newer cryptex to be reverted to that older one, in the event that the newer cryptex causes problems.

How macOS 26 Tahoe updates: 2 Finite state machines

Script-based updaters were underpowered and too unreliable to build the Signed System Volume and other components of macOS in Big Sur and beyond. When Apple was designing the software update subsystem to be used for its new Macs, it chose to develop a modern design from scratch, built around finite state machines. The end result is seen today in the log entries made when updating macOS.

At first sight those appear to be examples of everything the Unified log shouldn’t be. From the initial entries reporting the softwareupdated service is checking for updates, there’s a succession of huge and apparently incomprehensible entries in the log that surely belong somewhere else. In fact we’re given a remarkable step-by-step account of some of the most elegant and successful engineering design in macOS that reveals its inner workings. It also shows how Apple is now able to detect and fix update problems in real-time.

Finite state machine

This is a formal model used widely in computing to design, describe and implement a machine or automaton that can only exist in one of a finite number of states. Its state changes in response to defined events, which result in actions that in turn determine its transition to its next state. Although some FSMs are non-deterministic and subject to chance, those in softwareupdated are governed by deterministic rules. This is illustrated in the excerpt below, extracted from a sequence of log entries for one of the FSMs run by softwareupdated when it’s working out what updates are required, early during macOS updating.

This FSM starts here in the top state shown in blue, where it’s scanning for an SFR update. If that’s successful (the event), its next action is to decide whether the update requires an update to Rosetta 2. If it does (the next event), then its action is to scan for Rosetta updates, and it then transitions to its next state of scanning for Rosetta. If that’s followed by the event that the scan succeeds, the next action is to decide whether an update to RecoveryOS is required, and so the FSM proceeds to work out what updates are required before starting to download and prepare them for installation.

This may appear long-winded, but FSMs can be described formally and from there implemented in code that is robust and correct, fundamental requirements for macOS updates. It also builds in flexibility to tailor each update to what that Mac requires.

Log documentation

The unified log is used by softwareupdated to document the operation of the several FSMs it runs. If an error occurs during software update, this enables its origin and causation to be established, one of the primary purposes of the log. Full detail has to be captured in entries at the time the FSM is running, as they can’t be recreated in retrospect.

As a result, every state transition, each event, and all actions are entered in full detail. The message field in those log entries identifies the FSM involved, reports its current state (S), the event (E), its action (A), and then provides full information about its current data. Those must enable the FSM to be recreated and run in the event that something goes wrong, to investigate and fix malfunction or failure.

Although those large and copious log entries are a challenge to browse, the architecture of the Unified log is designed to cope with them. Such long messages are stored separately in the warren of directories inside /var/db/uuidtext, and don’t burden the main log’s tracev3 log files.

FSMs

When softwareupdated checks for, discovers, downloads and prepares the macOS update from 26.2 to 26.3, the following named FSMs are identifiable in log entries:

  • SUMacControllerScanManager
  • scan[UUID]
  • SUMacControllerRecoveryOSManagerScan
  • update_downloader
  • SUMacControllerStateMachine
  • update[UUID]
  • SUMacControllerScanManager (again)
  • scan[UUID] (again)
  • SUMacControllerRecoveryOSManagerScan (again)

in the order in which they appear. In some cases, before the FSM is run, it’s loaded with Events that are detailed in the log, and provide further insight into what that FSM does.

The UUID used for FSMs and throughout softwareupdated is allocated at the start of these processes, before scanning for software updates. It’s referred to as “the SUCore SoftwareUpdate UUID”, and doesn’t appear to be the same as well-known UUIDs used elsewhere. However, as it’s a version 5 UUID it probably doesn’t contain any randomly generated content. This is worth bearing in mind, as it’s this UUID that is attached to Event Reports.

Real-time reporting

Many of us can recall macOS updates that have gone badly wrong, and some that had to be withdrawn or replaced because of their problems. Apple tackles that now using an event reporting system that provides real-time information about how every Mac being updated is progressing. This is anonymised, the only identifier being the UUID allocated to that software update by softwareupdated before starting to scan for updates.

At frequent stages during software update, softwareupdated updates its Event Report to reflect progress, and that’s automatically uploaded to Apple’s servers at an HTTPS address starting with xp.apple.com/report/ Although typically only just over 500 bytes in length, a typical Event Report contains the following named fields:
UUID, audienceType, batteryIsCharging, batteryLevel, currentBaseOSVersion, currentOSType, currentOSVersion, currentProductVersionExtra, dataFsCapacity, dataFsFree, deviceClass, deviceModel, event, eventTime, lowPowerMode, macPlatform, mandatoryUpdateEligible, mandatoryUpdateOptional, preSUStagingEnabled, preSUStagingMaxSize, preSUStagingOptionalSize, preSUStagingRequiredSize, preferredType, rampEnabled, rapidSecurityResponseCombo, rapidSecurityResponseInstalled, rapidSecurityResponseSemiSplat, reportVersion, result, storageCapacity, ucoreVersion, systemFsCapacity, systemFsFree, targetOSVersion, totalRequiredFreeSpace, updateType.

Most should be fairly self-explanatory, and in this case the event field was set to SUCoreOTAPreSUStagingDetermineStarted.

The first of these is sent less than one second after starting to scan for updates, when policy and sizing for the updates to be downloaded have just been determined, and that’s repeated after each significant stage until the Mac is rebooted to apply the update. I suspect there’s also a final Event Report sent once the Mac has booted into the updated macOS.

Apple is thus able to track progress for each UUID during the software update process. Should it detect a problem, for example a required component being unavailable, it should be able to take immediate action to address that, rather than having to wait for individual users to report errors or failures long after they occurred.

Summary

  • From Big Sur, software update uses a modern design based on finite state machines, completely replacing its old script-based system.
  • FSMs bring the greatly improved reliability necessary to install and build the Signed System Volume and other components of macOS.
  • The log contains detailed accounts of FSMs as they are run to accomplish the many phases of these complex software updates.
  • Those log entries could be used to recreate the FSM in the event of failure or error, e.g. as provided in a sysdiagnose.
  • Bulky message content in log entries is stored outside log files, in the /var/db/uuidtext directory.
  • Each software update is given its own UUID.
  • Update progress is reported to Apple frequently in Event Reports.
  • Event Reports can enable real-time detection and correction of problems in software updates.

How macOS 26 Tahoe updates 1

Although the way that macOS updates itself has changed beyond all recognition over the last few years, we tend to assume that it still works much as it did in the past, downloading a single update file, decompressing and installing that. This series of articles takes a deeper dive into what actually happens, and tries to explain how it differs from previous package updates.

This account is primarily based on a detailed analysis of log entries obtained from updating 26.2 to 26.3 on a Mac mini M4 Pro, supported by additional information obtained from updating virtual machines to 26.3. macOS updates have changed considerably even since Big Sur, but I believe that their mechanisms have remained more similar than they differ from those before.

Download size

One of the most basic and striking observations about macOS updates is their variation in size. Although those reported on many Apple silicon Macs making the same single-step update are similar, some are considerably greater. As updates aren’t offered in standalone form, and are only provided via Software Update or its command line equivalent softwareupdate, the only practical way to assess this is to update a range of virtual machines.

Software Update also reports two update sizes to the user: the first is given as a promise prior to the user initiating the update, the other displayed above the progress bar during downloading, in the progress window. A third figure can also be derived by obtaining the update through a local Content Caching Server. Results obtained for the update to 26.3 are shown in the table below.

When originally performed on the host Mac, the initial claimed and reported download sizes were both smaller at 3.68 GB.

Although sizes for the update from 26.1 to 26.3 are surprisingly slightly less than those from 26.2, these demonstrate that the greater the difference between the original and destination versions, the larger will be the size of the download, as expected. However, there is no evidence that any of these shared the same download size: each is different, as if tailored to the requirements for the original macOS. This is very different from a system offering three types of installer for Delta and Combo updates, and a whole-system Installer for upgrades from an earlier major version.

Installation sizing

Prior to the update being applied, its download and preparation is largely controlled by softwareupdated and its associates. Before any downloading is initiated, that calculates the disk space required to download and prepare each of the components required for the update, a task it refers to as CalculatePrepareSize. This is critical if the update is to ensure that it won’t run out of free space during the update, and is checked repeatedly during the downloading sequence, as individual components are prepared for installation.

CalculatePrepareSize calculates the following values:

  • Cryptex size requirement, consisting of 60 MB being 1.2 times the size of the app cryptex, and 7,748 MB being 1.2 times the size of the system cryptex, for a total of 7,809 MB.
  • Snapshot preparation size, consisting of snapshot installation size of 3,785 MB plus the cryptex size, for a total of 11,595 MB.
  • Snapshot apply size, consisting of twice the update partition size plus the update APFS reserve for 700 MB, plus 231 MiB for sealing, for a total of 931 MB.
  • Snapshot preparation size, consisting of snapshot installation size of 5,154 MB (a significant increase from previously) plus the cryptex size, for a total of 12,963 MB.

For any given version of macOS (ignoring RSRs and BSIs that may later replace them), each hardware architecture is thought to have its own pair of cryptexes, and they aren’t thought to differ between Macs of the same architecture. Thus, no matter which their original version of macOS, all Apple silicon Macs updating to macOS 26.3 should be provided with the same app and system cryptexes, of the same sizes.

Sizes for snapshot update and installation clearly differ according to the original version of macOS. Although almost self-evident, it’s important to remember that updating macOS from a previous major version will normally require greater free disk space than updating by a single minor or patch version.

Given the sizes above, it’s also obvious that components downloaded for macOS updates are compressed to substantially smaller sizes, so have to be decompressed on the Mac being updated. Thus, the download sizes reported to the user are far smaller than the free disk space required to prepare and install the update.

Main stages

The overall sequence of stages is:

  1. Identify update. Shortly after starting up, and at intervals of approximately 6 hours afterwards, softwareupdated tries to connect to Apple’s software update service to check whether there’s an update available for that Mac. Checks can also be initiated manually, or by apps like SilentKnight. If an update is found, the Mac and its current system are checked to determine whether it meets the requirements for that update.
  2. Check update size. CalculatePrepareSize estimates space required. If free space is insufficient for the calculated requirements, the update is aborted.
  3. Display progress. The progress window is displayed with its bar, and set points are allocated to stages of the finite state machine in softwareupdated to indicate to the user how far update download and preparation have progressed.
  4. Initial preparations. These include detailed identification of components to be downloaded and installed, and preparation of persistent data.
  5. Preflight. Download the ‘update brain’ used to perform the update phase, and perform preflight phases.
  6. Update Rosetta. Download any update for Rosetta 2.
  7. Update Recovery. Download any Recovery update.
  8. Download snapshot update. This takes 38% of the progress bar, and includes streaming decompression of contents, and download and decompression of the two cryptexes.
  9. Preflight Recovery.
  10. Prepare update. This includes many checks, including hashes of firmware updates, cryptexes, and contents of the updates. This takes 39% of the progress bar, but doesn’t appear to involve any decompression.
  11. Apply update. Reboot macOS into the control of the ‘update brain’ to install update including new firmware, create snapshot, build hash tree, seal and sign SSV, then continue the boot process from that.
  12. Kernel boot into updated macOS.
  13. Clean up and check for updates.

Because stage 11, applying the update, is run by the update brain, normal logging doesn’t take place, and no clear account can be made of what happens then.

From Big Sur onwards, the great majority of this is performed in what is effectively a single thread run on CPU Performance cores. This is readily seen when updating a virtual machine, for example. It’s thought that updates are constrained to use the equivalent of just a single P core to enable the user to continue working through a process that could take up to an hour. Thankfully, with the advent of faster models and continued engineering optimisations, this Mac mini took just 18 minutes from requesting the update to 26.3 until it was logged into and fully functional again.

In subsequent articles I will look in more detail at the stages listed above.

Conclusions

  • The greater the difference between the original and new macOS versions, the larger the update will be to download.
  • Updates are tailored to the individual requirements of the Mac being updated, and may differ considerably in size.
  • Detailed installation sizing is performed after the offer of the update, and is considerably larger than download size, as it includes all components after decompression.
  • Download and preparation account for just under 40% of the progress bar each. More than 20% is accounted for by other stages.
  • Applying the update is followed by kernel boot from the updated SSV.

❌