{"record":{"id":"927d88f82f101c79","repo":"pnpm/pnpm","slug":"failed-to-read-virtualstoredir-at-virtualstored","errorCode":null,"errorMessage":"Failed to read virtualStoreDir at \"${virtualStoreDir}\"","messagePattern":"Failed to read virtualStoreDir at \"(.+?)\"","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pnpm11/installing/linking/modules-cleaner/src/prune.ts","lineNumber":209,"sourceCode":"    }\n  }\n\n  return new Set(orphanDepPaths)\n}\n\nfunction getScopeFromPackageName (pkgName: string): string | undefined {\n  if (pkgName[0] === '@') {\n    return pkgName.substring(0, pkgName.indexOf('/'))\n  }\n  return undefined\n}\n\nasync function readVirtualStoreDir (virtualStoreDir: string, lockfileDir: string): Promise<string[]> {\n  try {\n    return await fs.readdir(virtualStoreDir)\n  } catch (err: any) { // eslint-disable-line\n    if (err.code !== 'ENOENT') {\n      logger.warn({\n        error: err,\n        message: `Failed to read virtualStoreDir at \"${virtualStoreDir}\"`,\n        prefix: lockfileDir,\n      })\n    }\n    return []\n  }\n}\n\nasync function tryRemovePkg (lockfileDir: string, virtualStoreDir: string, pkgDir: string): Promise<void> {\n  const pathToRemove = path.join(virtualStoreDir, pkgDir)\n  removalLogger.debug(pathToRemove)\n  try {\n    await rimraf(pathToRemove)\n  } catch (err: any) { // eslint-disable-line\n    logger.warn({\n      error: err,\n      message: `Failed to remove \"${pathToRemove}\"`,","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/pnpm/pnpm/blob/6261b7f388016d57ca6b90340342411cd1d0d00f/pnpm11/installing/linking/modules-cleaner/src/prune.ts#L191-L227","documentation":"While pruning extraneous packages from node_modules/.pnpm (the virtual store), pnpm lists the virtual store directory with fs.readdir. If that fails with anything other than ENOENT (permissions, I/O errors, EMFILE), it logs this warning and returns an empty list, so pruning is silently skipped for this run and stale package directories survive.","triggerScenarios":"fs.readdir(virtualStoreDir) throws a non-ENOENT error: EACCES/EPERM on node_modules/.pnpm, EIO from a failing disk, EMFILE under heavy fd pressure, or ENOTDIR when something replaced the .pnpm directory with a file.","commonSituations":"node_modules partially owned by root after mixing sudo and non-sudo installs; Docker volume permission mismatches; a stray file named .pnpm; failing disk; file-descriptor exhaustion from a watcher process.","solutions":["Check permissions and ownership of node_modules/.pnpm and fix them (chown -R $(whoami) node_modules), then re-run pnpm install.","If node_modules is disposable, remove it entirely and reinstall — the virtual store is rebuilt.","If the error was EMFILE or transient I/O, close fd-heavy processes (watchers, editors) and retry the install."],"exampleFix":"# before: pnpm warns \"Failed to read virtualStoreDir at .../node_modules/.pnpm\" during prune\nsudo chown -R \"$(id -un):$(id -gn)\" node_modules\npnpm install\n# after: virtual store readable, pruning proceeds","handlingStrategy":"try-catch","validationCode":"import fs from 'node:fs'\nimport path from 'node:path'\n\n// Before install, confirm the virtual store is a readable directory.\nfunction virtualStoreReadable (lockfileDir: string): boolean {\n  const dir = path.join(lockfileDir, 'node_modules/.pnpm')\n  try {\n    return fs.statSync(dir).isDirectory()\n  } catch (err: any) {\n    return err.code === 'ENOENT' // absent is fine\n  }\n}","typeGuard":null,"tryCatchPattern":"Follow the source shape: catch readdir errors, treat ENOENT as empty (normal fresh install), and downgrade all other codes to a warning plus empty result so the install proceeds without pruning: catch (err) { if (err.code !== 'ENOENT') log.warn(err); return [] }","preventionTips":["Never mix sudo and non-sudo pnpm installs in the same project directory.","In Docker, ensure the node_modules volume is owned by the container user.","Close fd-heavy watchers if you see EMFILE during installs."],"tags":["node-modules","virtual-store","permissions","prune","filesystem"],"backgroundTag":"filesystem-permission-denied","analyzedSha":"6261b7f388016d57ca6b90340342411cd1d0d00f","analyzedAt":"2026-08-17T18:30:54.750Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}