{"record":{"id":"477dafcb5aa32b21","repo":"pnpm/pnpm","slug":"failed-to-clean-up-after-global-bin-activation-pre","errorCode":null,"errorMessage":"Failed to clean up after global bin activation preparation failed.","messagePattern":"Failed to clean up after global bin activation preparation failed\\.","errorType":"exception","errorClass":"AggregateError","httpStatus":null,"severity":"error","filePath":"pnpm11/global/commands/src/globalActivation.ts","lineNumber":209,"sourceCode":"    await fs.promises.mkdir(opts.globalBinDir, { recursive: true })\n    backupDir = await fs.promises.mkdtemp(path.join(opts.globalBinDir, '.pnpm-bin-backup-'))\n    const savedBinSlots = await backupBinSlots({\n      actualBinNames,\n      backupDir,\n      globalBinDir: opts.globalBinDir,\n    })\n    const oldHashTarget = await readHashTarget(opts.hashLink)\n    return { actualBins, actualBinNames, backupDir, savedBinSlots, oldHashTarget }\n  } catch (preparationError) {\n    const cleanupResults = await Promise.allSettled([\n      ...(backupDir == null ? [] : [fs.promises.rm(backupDir, { recursive: true, force: true })]),\n      fs.promises.rm(opts.installDir, { recursive: true, force: true }),\n    ])\n    const cleanupErrors = cleanupResults.flatMap((result) => {\n      return result.status === 'rejected' ? [result.reason] : []\n    })\n    if (cleanupErrors.length > 0) {\n      throw new AggregateError(\n        [preparationError, ...cleanupErrors],\n        'Failed to clean up after global bin activation preparation failed.',\n        { cause: preparationError }\n      )\n    }\n    throw preparationError\n  }\n}\n\n/** The commands the group declares, mapped to the file each one runs. */\nasync function getActualBins (opts: ActivateGlobalInstallOptions): Promise<Map<string, string>> {\n  const actualBins = new Map<string, string>()\n  const binsByPackage = await Promise.all(opts.pkgs.map(async ({ manifest, location }) => {\n    return getBinsFromPackageManifest(manifest, location)\n  }))\n  for (const bins of binsByPackage) {\n    for (const { name, path: binPath } of bins) {\n      if (!opts.binsToSkip.has(name)) actualBins.set(name, binPath)","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/pnpm/pnpm/blob/5b11d3a15b9022a2109cb18ed96a5d652630371f/pnpm11/global/commands/src/globalActivation.ts#L191-L227","documentation":"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.","triggerScenarios":"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.","commonSituations":"Same Windows lock/permission conditions as other activation failures; disk exhaustion occurring mid-preparation; antivirus interfering with rapid create/remove cycles in PNPM_HOME.","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function isPrepCleanupAggregate (err: unknown): err is AggregateError & { cause: unknown } {\n  return util.types.isNativeError(err) && Array.isArray((err as AggregateError).errors) && 'cause' in err\n}","tryCatchPattern":"try {\n  await activateGlobalInstall(opts)\n} catch (err) {\n  if (isPrepCleanupAggregate(err)) {\n    // err.cause = the original preparation error; err.errors also contains cleanup failures\n    // fix the cause first, then remove leftover install/backup dirs it reports\n    handlePreparationFailure(err.cause ?? err.errors[0])\n  }\n  throw err\n}","preventionTips":["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"],"tags":["global","activation","cleanup","aggregate-error","filesystem"],"backgroundTag":null,"analyzedSha":"5b11d3a15b9022a2109cb18ed96a5d652630371f","analyzedAt":"2026-08-16T13:18:59.198Z","schemaVersion":2},"datasetVersion":"2026-08-16T18:17:16.020Z"}