Let pnpm recreate node_modules during Next.js deploy
The install step captures pnpm's output, so pnpm has no TTY. When it needs to recreate node_modules (for example after a different pnpm major version installed it), it can't ask for confirmation and aborts with ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY. Pass --config.confirm-modules-purge=false to pnpm so it purges without asking. npm and yarn are left alone. Co-Authored-By: siGit Code <noreply@sigit.si>
Seto Elkahfi committed
Sep 30, 2026 at 07:27 UTC
052e2e8683b6fa64f166e8e22d91bd17dd7f7a47
1 file changed
+14
-10
crates/cli/src/cloud-deploy/process_deploy_nextjs_ssr.rs
+14
-10
@@ -215,16 +215,20 @@ pub async fn process_deploy_nextjs_ssr(env: Environment, config: Config) -> Resu
215
216
// Capture stdout/stderr so pnpm's output does not interleave with the
217
// spinner animation. On failure the captured output is printed for the user.
218
- let install_output = Command::new(package_manager)
219
- .args(["install", "--ignore-scripts"])
220
- .current_dir(source)
221
- .output()
222
- .map_err(|e| {
223
- anyhow!(fail_message(&format!(
224
- "Failed to spawn '{} install': {}",
225
- package_manager, e
226
- )))
227
- })?;
218
+ let mut install_command = Command::new(package_manager);
219
+ install_command.args(["install", "--ignore-scripts"]);
220
+ // With stdio captured pnpm has no TTY, so when it needs to recreate
221
+ // node_modules (store or linker change) it aborts with
222
+ // ERR_PNPM_ABORTED_REMOVE_MODULES_DIR_NO_TTY instead of prompting.
223
+ if package_manager == "pnpm" {
224
+ install_command.arg("--config.confirm-modules-purge=false");
225
+ }
226
+ let install_output = install_command.current_dir(source).output().map_err(|e| {
227
+ anyhow!(fail_message(&format!(
228
+ "Failed to spawn '{} install': {}",
229
+ package_manager, e
230
+ )))
231
+ })?;
232
233
if !install_output.status.success() {
234
install_spinner.stop_and_persist(&fail_symbol(), fail_message("Install failed."));