pnpm ERR_PNPM_IGNORED_BUILDS 怎麼修?把允許清單搬到 allowBuilds
升級 pnpm v11 後,如果安裝停在 ERR_PNPM_IGNORED_BUILDS,問題通常不是套件下載失敗,而是某個相依套件的 lifecycle script 沒有被專案明確允許。pnpm v11 把 strictDepBuilds 預設設為 true,也用 allowBuilds 取代舊的 build-dependency 設定,所以原本放在 package.json 的 pnpm 區塊不一定還會生效。
直接答案是:先找出被阻擋的套件,逐一判斷它是否真的需要執行安裝腳本,再把 true 或 false 寫進 workspace 根目錄的 pnpm-workspace.yaml。strictDepBuilds: false 可以作為短期遷移橋接,但不應取代可審查的允許清單。
這個錯誤到底在說什麼
pnpm 可以下載並安裝套件,但暫時不執行它的 install、postinstall 或其他 lifecycle script。這個邊界會讓安裝流程不會在沒有明確決策時自動執行相依套件程式碼;代價是需要 native binary、產生編譯產物或下載額外資源的套件,可能要先被允許才能正常使用。
錯誤通常會列出套件名稱:
ERR_PNPM_IGNORED_BUILDSIgnored build scripts: esbuild, sharpRun "pnpm approve-builds" to pick which dependencies should be allowed to run scripts.這份清單是排查起點,不是可以直接複製成 allowBuilds 的答案。套件名稱、版本、引入它的依賴路徑和目前執行環境,都要在同一個 lockfile 下確認。
先找出誰被擋住
先從 workspace 根目錄檢查 pnpm 目前認為哪些 build script 尚未處理:
pnpm ignored-builds接著用實際套件名稱追依賴來源,查看它宣告了哪些 script:
pnpm why esbuildpnpm view esbuild scripts --jsonpnpm why 用來回答「哪個直接或間接依賴帶進它」,pnpm view 則用來查看 registry manifest 的 script。兩個結果都不能單獨證明腳本安全;它們只是讓你知道要審查哪個 package 和哪個版本。
如果錯誤只在 CI 出現,請把 CI 使用的 Node.js、pnpm 版本、lockfile 和套件名稱一起記下來。不要先清掉整個 store 再重跑,否則可能失去能重現原始差異的條件。
把決策寫進 pnpm-workspace.yaml
allowBuilds 是以套件名稱為 key 的布林值 map:true 允許該套件的 build script 執行,false 則記錄為刻意拒絕。
allowBuilds: esbuild: true sharp: true fsevents: false這段設定要放在 workspace root 的 pnpm-workspace.yaml,不是放在某個子套件的 package.json。如果是 monorepo,先確認執行 pnpm install 時使用的 workspace root,避免把設定寫到不會被讀取的資料夾。
也可以讓 pnpm 透過互動式指令寫入決策:
pnpm approve-builds或直接列出要允許與拒絕的套件:
pnpm approve-builds esbuild sharp '!fsevents'執行後仍要檢查 YAML diff。approve-builds 會替你修改設定檔,並不會替你判斷每個相依套件是否應該信任。
從 pnpm v10 的設定遷移
舊專案可能有這種 package.json:
{ "pnpm": { "onlyBuiltDependencies": ["esbuild"], "ignoredBuiltDependencies": ["fsevents"] }}pnpm v11 的做法是改成 workspace 設定:
allowBuilds: esbuild: true fsevents: falsepnpm v11 的 release note 也列出 .npmrc 只保留 registry 與認證相關設定、pnpm 專屬設定集中到 pnpm-workspace.yaml 或 global config.yaml。因此,遷移時不要保留兩份互相競爭的設定並期待 pnpm 自動合併;舊區塊應逐項對照後移除或明確標註用途。
如果專案是從 pnpm v10 升級,可以先在分支執行官方 migration 工具,再逐行審查產生的 allowBuilds。特別留意把「曾經被允許」和「現在仍然需要執行」分開,避免把歷史累積的依賴全部自動核准。
CI 要驗證的是乾淨安裝
修改 allowBuilds 後,CI 應使用固定 pnpm 版本與 frozen lockfile,確認本機決策能在沒有舊 node_modules 的情況下重現:
pnpm ignored-buildspnpm install --frozen-lockfilepnpm run build本機要模擬全新安裝時,可以刪除目前專案的 node_modules 後再執行同一組指令;在 CI 則優先使用乾淨 runner,或清楚失效可能藏住問題的依賴快取。pnpm-lock.yaml 和 pnpm-workspace.yaml 要一起 review,因為套件版本改變也可能改變它是否含有 lifecycle script。
如果套件已在 allowBuilds 設為 true,但安裝仍然失敗,這是另一層問題:檢查 Node.js 版本、作業系統、compiler toolchain、optional dependency 與套件自己的安裝說明。允許 script 只代表它可以執行,不保證 native compilation 一定成功。
strictDepBuilds: false 能不能直接解決
可以暫時把它設為 false,讓未處理的 build script 不再直接把安裝變成失敗,但這只會隱藏審查訊號:套件可能安裝完成,應用程式卻在執行時找不到編譯產物。
strictDepBuilds: falseallowBuilds: esbuild: true這種設定比較適合短期遷移或先收集依賴清單。正式 CI 應逐步補上 allowBuilds,並讓 pnpm ignored-builds 的剩餘輸出成為可處理的檢查結果。不要用全允許的設定把所有相依套件腳本一次打開,因為那會讓原本的供應鏈審查邊界失去意義。
如果你同時遇到 package.json 裡的 overrides 或 patchedDependencies 沒有效果,可以再看 pnpm v11 的 package.json 設定搬遷;那篇處理的是設定檔位置,本文則聚焦被忽略的 build script。
驗證完成的判斷方式
把這次修正視為一次依賴信任決策,完成條件至少包括:
pnpm ignored-builds剩下的套件都有明確理由。allowBuilds在 workspace root,且列出的 package name 與 lockfile 一致。pnpm install --frozen-lockfile在固定版本的 CI 通過。- 需要產物的 build、test 或啟動指令實際成功。
pnpm-workspace.yaml的每個true都能由團隊說明為什麼需要。
這樣處理後,ERR_PNPM_IGNORED_BUILDS 就不只是「把 CI 解鎖」的錯誤,而是會留下可 review、可重現的 build policy。
常見問題
Q: 為什麼 pnpm 會說 build script 被忽略?
A: pnpm 找到相依套件的 lifecycle script,但目前專案的 allowBuilds 沒有允許它。先用 pnpm ignored-builds 找出套件,再判斷是否真的需要它執行安裝腳本,不要只複製錯誤訊息中的完整清單。
Q: allowBuilds 應該放在哪裡?
A: 放在 workspace 根目錄的 pnpm-workspace.yaml。pnpm v11 將許多 pnpm 專屬設定移出 package.json 的 pnpm field,也不再把一般專案設定當成 .npmrc 的責任;先確認 workspace root 再修改。
Q: 把 strictDepBuilds 設成 false 就好了嗎?
A: 它可以暫時避免未核准的 build script 直接讓安裝失敗,但不會替你決定哪些腳本可信,也不保證應用程式有完整的編譯產物。把它當成遷移橋接,最後仍應補上明確的 allowBuilds。
Q: 允許 build script 後,套件就一定能用嗎?
A: 不一定。允許只代表安裝腳本可以執行;Node.js 版本、平台差異、compiler、optional dependency 或套件本身的 runtime 設定仍可能造成另一個錯誤。
參考資料:
回報錯字、失效連結,或告訴我你想看的延伸主題。