pnpm/pnpm · error · UnexpectedStoreError
UNEXPECTED_STORE
UNEXPECTED_STORE
Error message
Unexpected store location
What it means
node_modules/.modules.yaml records the store directory the packages were hard-linked from. checkCompatibility compares it with the currently resolved store using path.relative (the only correct way to compare paths on Windows, per the linked issue) and also tolerates the legacy '.../v3' sibling store. A missing recorded store or a different location aborts the install because linking from a different store would break the hard-link layout.
Source
Thrown at pnpm11/installing/deps-installer/src/install/checkCompatibility/index.ts:31
storeDir: string
modulesDir: string
virtualStoreDir: string
}
): void {
if (!modules.layoutVersion || modules.layoutVersion !== LAYOUT_VERSION) {
throw new ModulesBreakingChangeError({
modulesPath: opts.modulesDir,
})
}
// Important: comparing paths with path.relative()
// is the only way to compare paths correctly on Windows
// as of Node.js 4-9
// See related issue: https://github.com/pnpm/pnpm/issues/996
if (
!modules.storeDir ||
path.relative(modules.storeDir, opts.storeDir) !== '' && path.relative(modules.storeDir, path.join(opts.storeDir, '../v3')) !== ''
) {
throw new UnexpectedStoreError({
actualStorePath: opts.storeDir,
expectedStorePath: modules.storeDir,
modulesDir: opts.modulesDir,
})
}
if (modules.virtualStoreDir && path.relative(modules.virtualStoreDir, opts.virtualStoreDir) !== '') {
throw new UnexpectedVirtualStoreDirError({
actual: opts.virtualStoreDir,
expected: modules.virtualStoreDir,
modulesDir: opts.modulesDir,
})
}
}
View on GitHub (pinned to 5b11d3a15b)
Solutions
- Run `pnpm install --force` to re-link node_modules from the current store
- If the store moved for a reason you control, restore the previous `store-dir` setting instead
- Set an explicit shared `store-dir` (CI, Docker volume) so the resolved path never drifts
- As a last resort, delete node_modules and reinstall
Example fix
# before: store location changed after editing store-dir pnpm install # ERR_PNMP_UNEXPECTED_STORE # after: either restore the old store path or force a re-link pnpm config set store-dir /previous/store/path # option A pnpm install --force # option B
Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'fs'
import { join, relative } from 'path'
import { parse } from 'yaml'
import { execSync } from 'child_process'
// Verify the store that built node_modules is the store pnpm resolves now
export function storeMatches (lockfileDir: string): boolean {
const modules = parse(readFileSync(join(lockfileDir, 'node_modules', '.modules.yaml'), 'utf8')) as { storeDir?: string }
const currentStore = execSync('pnpm store path', { encoding: 'utf8' }).trim()
return modules.storeDir != null && (
relative(modules.storeDir, currentStore) === '' ||
relative(modules.storeDir, join(currentStore, '../v3')) === ''
)
} Type guard
import util from 'util'
import { PnpmError } from '@pnpm/error'
export const isUnexpectedStoreError = (err: unknown): err is PnpmError =>
util.types.isNativeError(err) && (err as PnpmError).code === 'UNEXPECTED_STORE' Try / catch
try {
await mutateModules(mutations, opts)
} catch (err) {
if (isUnexpectedStoreError(err)) {
// err.expected is the recorded store dir; re-point config there, or purge and retry
await rimraf(join(opts.lockfileDir, 'node_modules'))
return mutateModules(mutations, opts)
}
throw err
} Prevention
- Pin `store-dir` explicitly in CI and Docker so the resolved path never drifts
- Do not move a project with its node_modules across users, machines, or mount points
- After changing store-dir, expect a one-time `pnpm install --force` to re-link
When it happens
Trigger: Install into node_modules where the recorded storeDir is set but matches neither the current store path nor path.join(storeDir, '../v3') via path.relative, or modules.storeDir is absent.
Common situations: Changed `store-dir` in .npmrc or pnpm-workspace.yaml; a different HOME/user running the install (the default store lives under the user's home); project moved between CI runners or containers with different mount points or drives.
Related errors
- UNEXPECTED_VIRTUAL_STORE
- CONFIG_CONFLICT_VIRTUAL_STORE_DIR_WITH_GLOBAL
- MODULES_BREAKING_CHANGE
- CONFIG_CONFLICT_FROZEN_STORE_WITH_FORCE
- FROZEN_STORE_INCOMPATIBLE_WITH_PNPR
AI-assisted analysis of pnpm/pnpm@5b11d3a15b (2026-08-16).
Data as JSON: /api/errors/dc371c3227005ef2.
Report an issue: GitHub.