pnpm/pnpm · warning

Failed to read virtualStoreDir at "${virtualStoreDir}"

Error message

Failed to read virtualStoreDir at "${virtualStoreDir}"

What it means

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.

Source

Thrown at pnpm11/installing/linking/modules-cleaner/src/prune.ts:209

    }
  }

  return new Set(orphanDepPaths)
}

function getScopeFromPackageName (pkgName: string): string | undefined {
  if (pkgName[0] === '@') {
    return pkgName.substring(0, pkgName.indexOf('/'))
  }
  return undefined
}

async function readVirtualStoreDir (virtualStoreDir: string, lockfileDir: string): Promise<string[]> {
  try {
    return await fs.readdir(virtualStoreDir)
  } catch (err: any) { // eslint-disable-line
    if (err.code !== 'ENOENT') {
      logger.warn({
        error: err,
        message: `Failed to read virtualStoreDir at "${virtualStoreDir}"`,
        prefix: lockfileDir,
      })
    }
    return []
  }
}

async function tryRemovePkg (lockfileDir: string, virtualStoreDir: string, pkgDir: string): Promise<void> {
  const pathToRemove = path.join(virtualStoreDir, pkgDir)
  removalLogger.debug(pathToRemove)
  try {
    await rimraf(pathToRemove)
  } catch (err: any) { // eslint-disable-line
    logger.warn({
      error: err,
      message: `Failed to remove "${pathToRemove}"`,

View on GitHub (pinned to 6261b7f388)

Solutions

  1. Check permissions and ownership of node_modules/.pnpm and fix them (chown -R $(whoami) node_modules), then re-run pnpm install.
  2. If node_modules is disposable, remove it entirely and reinstall — the virtual store is rebuilt.
  3. If the error was EMFILE or transient I/O, close fd-heavy processes (watchers, editors) and retry the install.

Example fix

# before: pnpm warns "Failed to read virtualStoreDir at .../node_modules/.pnpm" during prune
sudo chown -R "$(id -un):$(id -gn)" node_modules
pnpm install
# after: virtual store readable, pruning proceeds
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'node:fs'
import path from 'node:path'

// Before install, confirm the virtual store is a readable directory.
function virtualStoreReadable (lockfileDir: string): boolean {
  const dir = path.join(lockfileDir, 'node_modules/.pnpm')
  try {
    return fs.statSync(dir).isDirectory()
  } catch (err: any) {
    return err.code === 'ENOENT' // absent is fine
  }
}

Try / catch

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 [] }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17). Data as JSON: /api/errors/927d88f82f101c79. Report an issue: GitHub.