{"record":{"id":"272bc3372f8f2203","repo":"pnpm/pnpm","slug":"project-inaccessible","errorCode":"PROJECT_INACCESSIBLE","errorMessage":"Cannot access registered project \"${absoluteTarget}\": ${message}","messagePattern":"Cannot access registered project \"(.+?)\": (.+?)","errorType":"exception","errorClass":"PnpmError","httpStatus":null,"severity":"error","filePath":"pnpm11/store/controller/src/storeController/projectRegistry.ts","lineNumber":90,"sourceCode":"      )\n    }\n\n    const absoluteTarget = path.isAbsolute(target) ? target : path.resolve(path.dirname(linkPath), target)\n\n    // Check if project still exists\n    try {\n      await fs.stat(absoluteTarget)\n      projects.push(absoluteTarget)\n    } catch (err: unknown) {\n      // Only clean up if project directory no longer exists\n      if (util.types.isNativeError(err) && 'code' in err && err.code === 'ENOENT') {\n        await fs.unlink(linkPath)\n        globalInfo(`Removed stale project registry entry: ${absoluteTarget}`)\n        return\n      }\n      // Can't access project - throw error to prevent incorrect pruning\n      const message = util.types.isNativeError(err) ? err.message : String(err)\n      throw new PnpmError('PROJECT_INACCESSIBLE',\n        `Cannot access registered project \"${absoluteTarget}\": ${message}`,\n        {\n          hint: `To remove this project from the registry, delete the symlink at:\\n  ${linkPath}`,\n        }\n      )\n    }\n  }))\n\n  return projects\n}\n","sourceCodeStart":72,"sourceCodeEnd":101,"githubUrl":"https://github.com/pnpm/pnpm/blob/6261b7f388016d57ca6b90340342411cd1d0d00f/pnpm11/store/controller/src/storeController/projectRegistry.ts#L72-L101","documentation":"After resolving a project-registry entry's target (pnpm11/store/controller/src/storeController/projectRegistry.ts:90), fs.stat on the registered project directory failed with something other than ENOENT (which would clean up the stale entry). Errors like EACCES throw PROJECT_INACCESSIBLE because pruning based on unreadable projects could remove live data.","triggerScenarios":"`pnpm store prune` when a registered project directory exists but stat fails: permission denied on the project dir, an unreachable mount (stale NFS), or I/O errors - i.e. anything that is neither 'exists' nor 'gone'.","commonSituations":"Project directories owned by another user or root on shared machines; project on a network volume that is currently unmounted-but-erroring; restrictive ACLs created by backup tools.","solutions":["Restore readable access to the project dir named in the message: `chmod -R a+rX <absoluteTarget>` or fix the mount.","If the project is genuinely gone, remove the registry symlink at the linkPath given in the hint and re-run prune.","Ensure the user running prune can stat every registered project (same UID/permissions model)."],"exampleFix":"// before\n$ pnpm store prune\n# ERR_PNPM_PROJECT_INACCESSIBLE: Cannot access registered project \"/srv/app\"\n\n// after\n$ chmod -R a+rX /srv/app        # or: rm <linkPath-from-hint>\n$ pnpm store prune","handlingStrategy":"validation","validationCode":"import fs from 'node:fs'\nimport os from 'node:os'\nimport path from 'node:path'\n\n// every registered project target must be statable by this user before prune\nfunction registeredProjectsAccessible (projects: string[]): boolean {\n  return projects.every((dir) => {\n    try {\n      fs.statSync(dir)\n      return true\n    } catch (err: any) {\n      return err.code === 'ENOENT' // gone is fine (auto-cleanup); EACCES is not\n    }\n  })\n}","typeGuard":null,"tryCatchPattern":"try {\n  await store.prune()\n} catch (err) {\n  if ((err as NodeJS.ErrnoException).code === 'ERR_PNPM_PROJECT_INACCESSIBLE') {\n    // hint names the linkPath; restore access to the project dir or rm the symlink\n    throw err // do NOT auto-delete: that is exactly what the guard prevents\n  }\n  throw err\n}","preventionTips":["Keep registered project directories readable by the account that runs prune.","Unmount (rather than break) network volumes holding workspace projects before pruning.","When a project is truly deleted, remove its registry entry explicitly rather than relying on prune cleanup."],"tags":["store","permissions","prune","filesystem"],"backgroundTag":"permission-denied-accessing-directory","analyzedSha":"6261b7f388016d57ca6b90340342411cd1d0d00f","analyzedAt":"2026-08-17T18:30:54.750Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}