Python asked Windows for an update on every launch.
On 1 October Continuum's workers died at start with 42 GB of RAM free, because Windows had run out of commit. The AppX Deployment Service held 21.8 GB: the Python Install Manager asked App Installer for an update on every launch, a Claude Code plugin's hooks launched it twice for every prompt, edit and turn, and each update left 1.6 MB behind.
Out of commission
The workers ran out of memory with 42 GB of RAM free.
On the evening of 1 October a test window started Continuum's integration suite against a fresh
AppHost. The Swarm Worker's model and ingest roles never came up: each died at 22:08:59 with an
OutOfMemoryException, inside the Temporal SDK's DataConverter initializer.
No chat turn could end, so every chat, inference and projection test waited out its full timeout,
one to three minutes apiece, and the run crawled until Tristan stopped it.
The machine had 42 GB of RAM free and 1.2 GB of commit free, of 101.6 GB. Windows refuses an allocation once the commit charge reaches its limit, however much physical memory is idle, so a process starting up is the first to fail. Idle MSBuild nodes held 5 GB of it, and the session that owned them shut them down, but the largest committer was a Windows service.
At your service
A Windows service had committed 21.8 GB and was using 0.6.
The AppX Deployment Service (AppXSvc), which installs and updates app packages, had been running since the machine booted at 10:04 that morning. Twelve hours later it held 21.84 GB of private memory against the commit limit, a working set of 0.61 GB and 90,260 handles. A service whose commit is 36 times its resident set, with ninety thousand handles open, is leaking.
Its event log said what it had been doing: 2,997 of its last 3,000 events were the same update of
one package, PythonSoftwareFoundation.PythonManager, the Python Install Manager, through
App Installer, about 20 a minute since 20:47. The log keeps only so much, and between 18:26, its
oldest event, and midnight it records 5,980 of them. A reboot gave the memory back, AppXSvc started
again at 0.1 GB, and by 10:24 the next morning it was at 2.0 GB and climbing.
Hooked on a feeling
Every Claude Code hook launched Python twice, and every launch asked for an update.
Tristan
"What's causing it? Is it WSL2? Is it Continuum installing services? The Discord listener loop?"
It was none of the three, and nothing in Continuum runs Python. Claude watched process creation for 40 seconds
and caught the launcher in the act: py.exe -3 …\security-guidance\2.0.8\hooks\security_reminder_hook.py,
started from Git Bash, and a moment later the interpreter it chose.
security-guidance is a Claude Code plugin from Anthropic's official marketplace. Its
hook runs on every prompt, after every file edit, and at the end of every turn and every subagent,
in every session on the machine, and that evening there were five. Before each run its launcher,
sg-python.sh, looks for an interpreter again, trying python3.13 down to
python3.10, then python3, python and py -3.
Here only py -3 answered, so each hook launched it twice, once to read its version and
once to run. The updates in the log arrived in pairs, each pair within the same second.
py.exe was the Install Manager's app execution alias. The package was installed from
python.org's .appinstaller, and its manifest declares uap13:AutoUpdate
with an update check on launch, at most once every 24 hours. Windows started an update on every
activation instead. Its record of the last check had stood at 30 March for six months, and no event
ever recorded one of these updates finishing.
Get-AppPackageAutoUpdateSettings -PackageFamilyName PythonSoftwareFoundation.PythonManager_3847v3x7pw1km
# CheckForUpdatesOnLaunch : True
# HoursBetweenUpdateChecks : 24
# LastCheckedForUpdates : 30/03/2026 21:23:31
# Microsoft-Windows-AppXDeploymentServer/Operational, event 603, once per launch of py.exe:
# Started deployment UpdateUsingAppInstallerOperation operation on a package with main parameter
# PythonSoftwareFoundation.PythonManager_26.3.240.0_x64__3847v3x7pw1km and Options 0 and 0.Check, please
Switching the check off didn't stop it.
Claude's first remedy, which it said would stop the updates, was the package's own setting.
Tristan ran Set-AppPackageAutoUpdateSettings … -CheckOnLaunch $false in an elevated
shell, and the settings read back False, with the last check now 10:30. Three launches of
py.exe then started three updates. The interpreter run directly, outside the alias,
started none, and neither did the Store's python.exe stub. So Windows starts the update
for the alias whatever the interval and whatever the setting says.
Two readings of AppXSvc that morning put a price on each update. Between 10:23:52 and 10:31:06 it ran 176 of them, and its commit rose by 0.28 GB and its handles by 866: about 1.6 MB and 5 handles an update, never given back. The night before agrees. At 1.6 MB, 21.84 GB is about 13,700 updates over 12 hours, or 19 a minute, against the 20 a minute the log showed.
Under new management
Python without the Install Manager starts no updates.
Tristan
"We need to purge everything."
The manager's runtime went first, through its own pymanager uninstall --purge, then the
package, then every folder, registry key and file association it had left. Tristan installed Python
3.14.8 from python.org's standard installer, which puts an ordinary py.exe launcher in
the Windows folder and no app package anywhere, and rebooted.
Then the hook's own launcher ran 22 times from Git Bash, through py -3 and through
python. It started no updates. AppXSvc sat at 0.03 GB and 683 handles throughout,
and commit stood at 77 GB free.
The leak needed all three: an app package that checks for its updates on launch, a plugin that finds its interpreter before every run, and five sessions sharing one machine, as sessions here do. Together they ran 5,980 updates in under six hours, and Windows kept 1.6 MB of each.
The report, for Microsoft
Summary. For an MSIX package that declares uap13:AutoUpdate with an
OnLaunch update check, every activation of its app execution alias starts an
UpdateUsingAppInstallerOperation in AppXSvc. The 24-hour
HoursBetweenUpdateChecks is not applied, and neither is
CheckForUpdatesOnLaunch = False set with Set-AppPackageAutoUpdateSettings.
Each operation leaves about 1.6 MB of private memory and 5 handles in AppXSvc, and none of it was
released while the service ran. A caller that launches the alias often exhausts the system commit
limit within a day, and new processes then fail with out-of-memory errors while physical memory is
free.
| Environment | |
|---|---|
| Windows | Windows 11 Pro 25H2, build 26200.9457 |
| App Installer | Microsoft.DesktopAppInstaller 1.29.379.0 |
| Package | PythonSoftwareFoundation.PythonManager_26.3.240.0_x64__3847v3x7pw1km, signature kind Developer |
| Installed from | https://www.python.org/ftp/python/pymanager/pymanager.appinstaller |
| Its update settings | <OnLaunch HoursBetweenUpdateChecks="24"/>, ForceUpdateFromAnyVersion true |
| Auto-update settings read back | CheckForUpdatesOnLaunch True, HoursBetweenUpdateChecks 24, LastCheckedForUpdates 2026-03-30 21:23:31, Version 26.0.240.0 (26.3.240.0 installed), PolicySource Default |
To reproduce:
- Install the Python Install Manager from the
.appinstallerabove. - Run
py -3 -c passthrough the alias in%LOCALAPPDATA%\Microsoft\WindowsApps, a few hundred times. - Read
Microsoft-Windows-AppXDeploymentServer/Operationalfor event 603, and AppXSvc's private bytes and handle count.
Expected: at most one update check every 24 hours, none once
CheckForUpdatesOnLaunch is false, and an operation's memory released when it ends.
Actual:
- One event 603 per launch, 1:1, before and after the setting was changed: three launches at 10:32 on 2 October started three operations.
- No other event shares an operation's activity id, so none is recorded as finishing.
- The same interpreter run directly, not through the alias, starts none.
- 176 operations between two readings raised AppXSvc's commit by 0.28 GB and its handles by 866.
- After 12 hours of uptime, AppXSvc held 21.84 GB committed, a 0.61 GB working set and 90,260 handles, with 1.2 GB of the system's 101.6 GB commit left.
- The event log counted 5,980 operations between 18:26 and midnight on 1 October, and 1,616 on 2 October before the package was removed.
Workaround: uninstall the package. A reboot, or a restart of AppXSvc, releases what it has already leaked.