pnpm/pnpm · error · AggregateError
Failed to clean up after global bin activation preparation f
Error message
Failed to clean up after global bin activation preparation failed.
What it means
prepareGlobalInstall backs up existing bin slots, materializes the fresh install, and reads the old hash-link target; if any preparation step throws, it removes backupDir and installDir as cleanup. When that cleanup itself fails, the preparation error plus cleanup errors are wrapped in an AggregateError ('Failed to clean up after global bin activation preparation failed.') whose `cause` is the original preparation error.
Source
Thrown at pnpm11/global/commands/src/globalActivation.ts:209
await fs.promises.mkdir(opts.globalBinDir, { recursive: true })
backupDir = await fs.promises.mkdtemp(path.join(opts.globalBinDir, '.pnpm-bin-backup-'))
const savedBinSlots = await backupBinSlots({
actualBinNames,
backupDir,
globalBinDir: opts.globalBinDir,
})
const oldHashTarget = await readHashTarget(opts.hashLink)
return { actualBins, actualBinNames, backupDir, savedBinSlots, oldHashTarget }
} catch (preparationError) {
const cleanupResults = await Promise.allSettled([
...(backupDir == null ? [] : [fs.promises.rm(backupDir, { recursive: true, force: true })]),
fs.promises.rm(opts.installDir, { recursive: true, force: true }),
])
const cleanupErrors = cleanupResults.flatMap((result) => {
return result.status === 'rejected' ? [result.reason] : []
})
if (cleanupErrors.length > 0) {
throw new AggregateError(
[preparationError, ...cleanupErrors],
'Failed to clean up after global bin activation preparation failed.',
{ cause: preparationError }
)
}
throw preparationError
}
}
/** The commands the group declares, mapped to the file each one runs. */
async function getActualBins (opts: ActivateGlobalInstallOptions): Promise<Map<string, string>> {
const actualBins = new Map<string, string>()
const binsByPackage = await Promise.all(opts.pkgs.map(async ({ manifest, location }) => {
return getBinsFromPackageManifest(manifest, location)
}))
for (const bins of binsByPackage) {
for (const { name, path: binPath } of bins) {
if (!opts.binsToSkip.has(name)) actualBins.set(name, binPath)View on GitHub (pinned to 5b11d3a15b)
Solutions
- Unwrap `error.cause` (or errors[0]) and fix the underlying preparation failure first
- Manually remove the leftover installDir/backupDir if they still exist after the failure
- Fix permissions and locks on the global dirs, ensure free disk space, then re-run the command
Defensive patterns
Strategy: try-catch
Type guard
function isPrepCleanupAggregate (err: unknown): err is AggregateError & { cause: unknown } {
return util.types.isNativeError(err) && Array.isArray((err as AggregateError).errors) && 'cause' in err
} Try / catch
try {
await activateGlobalInstall(opts)
} catch (err) {
if (isPrepCleanupAggregate(err)) {
// err.cause = the original preparation error; err.errors also contains cleanup failures
// fix the cause first, then remove leftover install/backup dirs it reports
handlePreparationFailure(err.cause ?? err.errors[0])
}
throw err
} Prevention
- Check permissions and free disk space in the global dir before scripted installs
- Keep AV/lockers away from PNPM_HOME so cleanup rm calls can succeed
- Always inspect `cause` of AggregateErrors — the visible message hides the real trigger
When it happens
Trigger: A preparation step fails (e.g. backing up or reading a bin slot) AND the Promise.allSettled rm of backupDir/installDir rejects — locked or read-only files, permission problems, or disk full.
Common situations: Same Windows lock/permission conditions as other activation failures; disk exhaustion occurring mid-preparation; antivirus interfering with rapid create/remove cycles in PNPM_HOME.
Related errors
- Failed to clean up after global bin activation failed.${rema
- Failed to clean up replaced global installs
- GLOBAL_BIN_ROLLBACK_FAILED
- GLOBAL_BIN_UNSUPPORTED_TYPE
- Failed to remove Windows bin shims for ${cmd}
AI-assisted analysis of pnpm/pnpm@5b11d3a15b (2026-08-16).
Data as JSON: /api/errors/477dafcb5aa32b21.
Report an issue: GitHub.