2088 字
10 分鐘

pnpm install 出現 Operation not permitted?先查 hardlink 與 clone

pnpm install 出現 Operation not permitted 時,錯誤位置常在 node_modules,但原因未必是「目前使用者沒有讀寫專案目錄」。pnpm 可能正在把內容從 store 以 hardlink 或 copy-on-write clone 匯入,而目前的檔案系統、容器權限或掛載方式拒絕了那個操作。

pnpm 12.4.1 在 2026 年 9 月 10 日修正了這條路徑:packageImportMethod 設為 auto 或 clone-or-copy 時,hard link/COW clone 被檔案系統拒絕,會改用 copy。明確指定 hardlink 或 clone 時,仍會保留錯誤,因為那代表專案刻意要求特定的匯入方式。

所以第一個判斷不是刪除 node_modules,而是先確認 pnpm 版本、匯入策略和 store 是否位於另一個檔案系統。

先把錯誤分成四種#

症狀較可能的原因第一個動作
Operation not permitted,發生在匯入 store 的檔案hardlink 或 COW clone 被檔案系統拒絕查 pnpm 版本與 packageImportMethod
明確使用 hardlink 或 clone 時持續失敗設定要求的能力不存在,fallback 不會介入改成 auto 或 copy,或把 store/專案移到合適的檔案系統
Docker 建置時出現 Invalid cross-device linknested node_modules 保留操作跨越 mount 或 layer先升級到 pnpm 12.4.1,再檢查 store 與 build layer
Windows 顯示 Access denied 且重試很久檔案鎖定或暫時性權限競爭更新 pnpm,再找出佔用檔案的程序

同一個 Operation not permitted 文字可能來自不同作業系統。不要只複製最後一行錯誤給別人,至少要保留完整命令、pnpm 版本、Node 版本、執行環境和 packageImportMethod。

先收集可比對的環境資訊#

在失敗的同一個專案目錄執行:

Terminal window
pnpm --version
node --version
pnpm config get --location=project packageImportMethod
pnpm config get store-dir
pnpm config list --location=project

再檢查專案設定是否有明確要求特殊匯入方式:

Terminal window
rg -n 'packageImportMethod|nodeLinker|storeDir' pnpm-workspace.yaml package.json 2>/dev/null || true

最後一個命令若某個檔案不存在會回傳錯誤,不代表 pnpm install 的原因;重點是找出是否存在 pnpm-workspace.yaml 或其他專案設定。也要確認 store 和專案是不是位於不同 volume、bind mount、Docker layer、網路磁碟或特殊 checkout。

packageImportMethod 應該怎麼選#

常見設定可以先這樣理解:

行為適合情境
auto依作業系統與檔案系統選擇可行方式一般本機、CI 與不確定的容器環境
copy直接複製檔案,較少依賴檔案系統能力rootless container、特殊 checkout、排錯或可接受較多 I/O
hardlink要求 hard link,節省空間但需要相容的 store 與檔案系統已確認同一檔案系統且需要 inode 共用
clone-or-copy先嘗試 COW clone,失敗再複製支援 reflink 的環境,且不希望 clone 失敗就中止

pnpm 12 的專案設定放在 workspace 根目錄的 pnpm-workspace.yaml:

packageImportMethod: auto

如果你的部署環境已知不允許 hardlink 或 reflink,可以在該環境明確使用:

packageImportMethod: copy

這個選擇是效能與相容性的取捨,不是單純的「哪個比較新」。copy 可能增加安裝時間與磁碟使用量,但比讓 CI 因為一項不必要的檔案系統能力而失敗更容易預測。若團隊依賴 hardlink 的空間效率,應修正 store 和專案的掛載位置,而不是默默改成 copy。

pnpm 12.4.1 會自動 fallback 的邊界#

官方 12.4.1 release note 明確涵蓋下列案例:

  • EdenFS checkout 沒有 hard link 時,auto 或 clone-or-copy 會改用 copy。
  • rootless container 拒絕 clone syscall 時,auto 或 clone-or-copy 會改用 copy。
  • Android 上拒絕 hardlink 或 reflink 的檔案系統也會改用 copy。
  • Docker 建置保留套件內 nested node_modules 時,不再因 Invalid cross-device link 直接失敗。

但以下情況仍不會被這個修正掩蓋:

  • 你明確設定 packageImportMethod: hardlink 或 clone。
  • 失敗其實是 store、node_modules 或專案目錄的傳統讀寫權限。
  • registry、憑證、生命週期腳本或套件本身的 build script 失敗。
  • 磁碟已滿、inode 用盡、唯讀 mount 或容器的 quota 已達上限。

因此「升級到 12.4.1」是第一個可驗證的修正,不是所有權限錯誤的萬用解答。

rootless container 和 Docker 的排錯順序#

容器內最容易混淆的是:pnpm 可以讀取 store,不代表核心允許它對 store 做 hardlink 或 clone。先在相同容器和相同使用者下確認設定,再決定是否使用 copy:

Terminal window
pnpm config get store-dir
pnpm config get --location=project packageImportMethod
pnpm install --frozen-lockfile

如果目前是明確的 hardlink 或 clone,先在可拋棄的 build job 改成 auto;rootless 環境仍失敗時再改成 copy。若 store 透過 bind mount 放在另一個 volume,也要把它當成獨立變數測試,不要只改檔案 owner。

Dockerfile 不需要為了這個錯誤先加入 chmod 777 或以 root 執行整個 install。先固定 Node、pnpm、store 路徑和 mount,再比較 cold install、warm install 與 frozen install。若只是 nested node_modules 的跨裝置保留錯誤,12.4.1 的修正應先被納入測試矩陣;如果仍失敗,再縮小到最小套件和最小 Docker layer。

Windows 與一般檔案權限不要混為一談#

12.4.1 也調整了 Windows 檔案操作的權限錯誤重試,但 Access denied 仍可能是編輯器、測試程序、病毒掃描器或另一個 pnpm 行程持有檔案。先關閉會寫入 node_modules 的程序,再重現一次;若只有特定檔案被佔用,保留檔名和程序資訊。

若錯誤發生在刪除舊 node_modules,新的錯誤訊息可能會透過 ERR_PNPM_PACKAGE_MANAGER_REMOVE_MODULES_DIR 指出無法清理的實際檔案或目錄。這比直接整棵刪掉更適合拿來定位問題。

驗證修正,不要只看 install 變綠#

完成版本或設定變更後,在乾淨工作副本跑一次:

Terminal window
pnpm --version
pnpm install --frozen-lockfile
git diff --exit-code -- pnpm-lock.yaml
pnpm test
pnpm build

若專案沒有 test 或 build script,請換成實際的 lint、型別檢查和打包命令。要另外記錄:

  • cold store 和 warm store 是否都成功。
  • 本機與 CI 是否使用同一個 packageImportMethod。
  • node_modules 是否真的由預期的使用者建立。
  • install 是否執行了 build script,以及產物是否可被讀取。
  • 變更是否只是 package manager 設定,而不是順便重寫 lockfile。

不要用一次成功的 warm install 證明環境已修好;store 已經有檔案時,可能沒有走到原本失敗的匯入路徑。

這三個動作不要當成第一個修正#

  1. 不要用 sudo 執行專案 install,再把 root 建立的 node_modules 留給一般使用者。
  2. 不要把整個專案或 node_modules chmod 777,這會掩蓋 mount、owner 和程序鎖定問題。
  3. 不要先刪除 store、lockfile 和 Docker cache;先保存錯誤與設定,否則無法知道是哪個變數改變。

若要清理,先在可回復的分支或 disposable runner 做,並只清理已確認的 node_modules 或 store 路徑。不同問題應保留不同的最小重現,不要用一次大清理取代診斷。

結論:先讓 pnpm 選擇可行的匯入方式#

pnpm install 的 Operation not permitted 若出現在 hardlink 或 COW clone 路徑,常常是檔案系統能力和設定的組合問題。pnpm 12.4.1 已讓 auto 與 clone-or-copy 在多個受限環境 fallback 到 copy,但明確的 hardlink、clone 和一般檔案權限錯誤仍要分開處理。

最短排錯路徑是:記錄 pnpm/Node/store、查 packageImportMethod、在相同容器或 CI runner 重現,再用 frozen install、測試和 build 驗證。先修正一個變數,才知道真正解決的是檔案系統問題還是剛好換了環境。

常見問題#

Q: pnpm 12.4.1 會修好所有 Operation not permitted 嗎?#

A: 不會。它主要修正 hardlink 或 COW clone 被拒絕時的匯入 fallback。若是唯讀 mount、磁碟 quota、一般 owner、檔案鎖定或生命週期腳本失敗,仍要依原始錯誤排查。

Q: 已經使用 packageImportMethod: hardlink,應該直接改成 copy 嗎?#

A: 先確認 hardlink 是否為必要的空間最佳化。如果只是想讓 rootless CI 通過,可以在該環境用 auto 或 copy;如果 production 依賴 hardlink,則應修正 store/專案的檔案系統與掛載方式,並保留兩種環境的測試結果。

Q: 可以刪除 pnpm-lock.yaml 重新安裝嗎?#

A: 不要把刪 lockfile 當成檔案系統錯誤的修正。先用既有 lockfile 做 frozen install;只有在已理解依賴變更且有隔離分支時,才重新解析並逐項審查 diff。

參考資料:

pnpm v12.4.1 release notes

pnpm Settings

pnpm install

pnpm install 出現 Operation not permitted?先查 hardlink 與 clone
https://laplusda.com/posts/pnpm-install-operation-not-permitted-hardlink-copy/
作者
Zero
發佈於
2026-09-15
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。