Skip to content

Retries and Timeouts

Rod Christiansen edited this page Sep 5, 2026 · 2 revisions

Retries and Timeouts

Retry behaviour is not configurable from the manifest. There are no retries, retrywait or timeout keys in this build; the numbers below are compiled in. Only MSI installs retry at all, and only one type of item gets the aggressive policy. This page gives the exact figures and what a failure does to the rest of the run.

MSI retries

Two policies, chosen per item:

Installer helper Everything else
Attempts 10 5
Wait between attempts 15 seconds 10 seconds
Retries on Any non-zero exit code Only 1603, 1619, 1620, 1612

An item gets the first policy when its name contains System Binary Installer or sbin-installer, or when its filename contains sbin-installer, all case-insensitively. Those items log CRITICAL PACKAGE: {name} - using aggressive retry strategy on entry, and on exhaustion fail with CRITICAL: {name} failed with exit code {n} after {a} attempts. System cannot continue without this package. Everything else fails with MSI installer failed with exit code: {n}.

A retry logs at Warning: MSI error {code}, retrying in {n} seconds... (attempt {a}/{max}).

Nothing else retries. A ps1, exe, nupkg or pkg item that exits non-zero fails on the first attempt. Downloads do not retry either — one GET per item, and a non-success status fails the item immediately with Download failed: {StatusCode}.

Installer mutex collisions

Exit code 1618, ERROR_INSTALL_ALREADY_RUNNING, is not treated as a failure. Another installer — during the Enrollment Status Page (ESP) this is usually the Intune Management Extension — held the global Windows Installer transaction.

Before every launch attempt, BootstrapMate waits on Global\_MSIExecute for up to 600 seconds, polling every 2 seconds. If the wait times out it launches anyway and logs Windows Installer still busy after 600s; launching anyway (a 1618 will be retried, not failed).

If the launch does come back 1618, the run increments a collision counter, waits for idle again, sleeps 3 seconds, and then decrements the attempt counter so the collision costs nothing from the retry budget. The line is written at log level Debug: MSI already running (1618) - waiting for the active installer to finish, then retrying (collision {n}, not counted as a failed attempt).

The cap is 30 collisions. Exceeding it throws MSI installer for {name} could not start: another Windows Installer transaction held the system across {n} collisions. With the 600-second idle wait in front of each attempt, an item stuck behind a genuinely wedged installer can therefore occupy the run for a long time before that cap is reached.

Two supporting details. The idle wait treats a mutex it cannot open — absent, ACL-denied or abandoned — as idle and returns immediately, so a permissions quirk never blocks a bootstrap; the 3-second backoff exists because that early return would otherwise spin straight through all 30 collisions. And if msiexec.exe cannot be started at all, that is logged (Failed to start msiexec.exe (Process.Start returned null); backing off and retrying) and does consume an attempt, so a persistent launch failure cannot loop forever. That path has a sharp edge: exhausting the attempts through launch failures alone leaves the retry loop without raising an error, and the item is then reported as installed. Every ordinary failure raises inside the loop, so this is narrow — but it is another reason not to treat a success line as proof. See Troubleshooting and Gotchas.

Timeouts

Operation Limit
Manifest and package downloads 100 seconds, the .NET default
Waiting for an installer or script to exit None
Windows Installer idle wait, per attempt 600 seconds
Run-summary POST to the reporting endpoint 15 seconds
Waiting for another BootstrapMate instance 30 minutes
where.exe lookups for Chocolatey and sbin-installer 5 seconds
choco --version health check 5 seconds
choco cache clear during --force cleanup 10 seconds
Named pipe connect for --pipe 5 seconds

The NetworkTimeout setting is configurable through the registry, policy and the graphical app, and is not applied to the CLI's downloads. Treat the 100-second figure as fixed.

The second row matters most. Once an installer or script is launched, BootstrapMate waits for it to exit with no time limit at all, so a hung installer hangs the entire run. There is no donotwait equivalent, and no way to launch an item and move on.

If a second BootstrapMate starts while one is running, it waits on a global mutex, logging Another BootstrapMate instance is already running - waiting for it to finish. After 30 minutes it gives up with Timed out after 30 minutes waiting for another BootstrapMate instance to finish and exits 1.

What a failure does to the run

An item failure is caught, logged as Failed to install package {name}: {message}, marked failed in the progress dialog, and stepped over. The next item runs. The failed names are carried to the end of the run: the phase finishes as Failed with ExitCode 1 and the names in LastError, LastRunVersion is not written, and the run summary reports success: false. The process still exits 0.

So the exit code is not a package-health signal, though everything else is. To judge a run, count Failed to install package lines in the log, read the phase Stage, or check whether C:\ProgramData\ManagedBootstrap\cache is empty — a cached file is kept only when its install failed.

The exceptions, where the run does stop and exit 1, are failures outside the item loop: the manifest cannot be downloaded or parsed, or no manifest URL can be resolved at all. Those mark the phase Failed in the registry with the exception message in LastError.

There is no reboot handling and no resume: /norestart is passed to every MSI, nothing detects a pending reboot, and no state is carried between runs beyond the registry status. The real retry mechanism for a failed item is the next run — the MSI registers a BootstrapMate Self-Heal scheduled task that re-runs the whole manifest daily at 03:00 as SYSTEM, and items that already succeeded are installed again.

The macOS build differs here: it retries downloads per item with manifest-settable retries and retrywait keys, and supports donotwait. See https://github.com/bootstrapmate/bootstrapmate-macintosh/wiki/Retries-and-Timeouts.

See also

Clone this wiki locally