{"record":{"id":"e9d9554943354bce","repo":"mui/material-ui","slug":"failed-to-install-dependencies","errorCode":null,"errorMessage":"Failed to install dependencies","messagePattern":"Failed to install dependencies","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/useReactVersion.mjs","lineNumber":106,"sourceCode":"        throw new Error(\n          `Version ${majorVersion} does not have version defined for the ${packageName}`,\n        );\n      }\n      packageJson.resolutions[packageName] = additionalVersionsMappings[majorVersion][packageName];\n    });\n  }\n\n  // add newline for clean diff\n  fs.writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}${os.EOL}`);\n\n  console.log('Installing dependencies...');\n  const pnpmInstall = childProcess.spawn('pnpm', ['install', '--no-frozen-lockfile'], {\n    shell: true,\n    stdio: ['inherit', 'inherit', 'inherit'],\n  });\n  pnpmInstall.on('exit', (exitCode) => {\n    if (exitCode !== 0) {\n      throw new Error('Failed to install dependencies');\n    }\n  });\n}\n\nconst [version = process.env.REACT_VERSION] = process.argv.slice(2);\nmain(version).catch((error) => {\n  console.error(error);\n  process.exit(1);\n});\n","sourceCodeStart":88,"sourceCodeEnd":116,"githubUrl":"https://github.com/mui/material-ui/blob/bdc96df2cb530fcdd60a7a7aabe37f610ce0f0a5/scripts/useReactVersion.mjs#L88-L116","documentation":"Thrown from the `exit` event handler of the spawned `pnpm install --no-frozen-lockfile` when that process exits with a non-zero code. By the time this runs, the script has already rewritten package.json with the new React resolutions, so the install itself is what failed. Note the throw is inside an async event handler, so it surfaces as an unhandled rejection rather than being caught by main().catch() — the surrounding promise has already settled.","triggerScenarios":"pnpm install returns non-zero: peer-dependency or resolution conflict; network or registry failure; invalid version string written into package.json.resolutions by the earlier steps; lockfile incompatible with the new resolutions; or `pnpm` not on PATH (in which case the spawn itself errors). Also fires when the resolutions point at versions that do not exist on the registry.","commonSituations":"CI with an empty or partially-warmed npm cache; corporate proxy blocking the registry; a typo'd version or tag passed to the script producing a bad resolution; switching React versions mid-branch leaving a dirty lockfile; runner image without pnpm installed.","solutions":["Reproduce manually: `pnpm install --no-frozen-lockfile` in the repo root and read the actual error.","Inspect `package.json` `resolutions` — if a value looks wrong, fix the version/tag passed to the script and re-run.","Verify `pnpm` is installed and on PATH (`which pnpm`, `pnpm --version`) and that the registry is reachable (`npm ping`).","If the lockfile is unsalvageable, regenerate it deliberately: remove `pnpm-lock.yaml` and re-run install."],"exampleFix":"// before\nconst pnpmInstall = childProcess.spawn('pnpm', ['install', '--no-frozen-lockfile'], {\n  shell: true,\n  stdio: ['inherit', 'inherit', 'inherit'],\n});\npnpmInstall.on('exit', (exitCode) => {\n  if (exitCode !== 0) {\n    throw new Error('Failed to install dependencies');\n  }\n});\n\n// after\nconst pnpmInstall = childProcess.spawn('pnpm', ['install', '--no-frozen-lockfile'], {\n  shell: true,\n  stdio: ['inherit', 'inherit', 'inherit'],\n});\nawait new Promise<void>((resolve, reject) => {\n  pnpmInstall.on('exit', (exitCode) => {\n    if (exitCode === 0) resolve();\n    else reject(new Error(`Failed to install dependencies (pnpm exit ${exitCode})`));\n  });\n  pnpmInstall.on('error', reject);\n});","handlingStrategy":"try-catch","validationCode":"// Pre-flight before invoking useReactVersion: confirm pnpm is on PATH and\n// the registry is reachable, so install is less likely to fail.\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nconst execAsync = promisify(exec);\n\nasync function assertInstallReady() {\n  try {\n    await execAsync('pnpm --version');\n  } catch {\n    throw new Error('pnpm not found on PATH; install it before running useReactVersion.');\n  }\n  try {\n    await execAsync('npm ping');\n  } catch {\n    throw new Error('npm registry unreachable; check network/proxy/registry config.');\n  }\n}","typeGuard":"// Narrows an unknown to a NodeJS spawn exit that the install handler can\n// inspect deterministically.\nfunction isNonZeroExit(\n  code: number | string | null,\n): code is number {\n  return typeof code === 'number' && code !== 0;\n}","tryCatchPattern":"// The current script throws from an async exit handler, which becomes an\n// unhandled rejection. Promisify the spawn so the failure flows through\n// main().catch and surfaces the real exit code.\nawait new Promise<void>((resolve, reject) => {\n  const child = childProcess.spawn('pnpm', ['install', '--no-frozen-lockfile'], {\n    shell: true,\n    stdio: 'inherit',\n  });\n  child.on('exit', (code) =>\n    code === 0 ? resolve() : reject(new Error(`pnpm install failed (exit ${code})`)),\n  );\n  child.on('error', reject);\n});","preventionTips":["Run `pnpm install --no-frozen-lockfile` manually after a failed run to see the real error before re-trying the script.","Validate the version/tag passed to the script up front — bad resolutions are the most common cause of the install failure.","Pin a working pnpm version via corepack/packageManager so runners do not regress.","In CI, cache the pnpm store and verify registry reachability before invoking the script.","If you maintain the script, promisify the spawn (see tryCatchPattern) so the error reaches main().catch instead of becoming an unhandled rejection."],"tags":["pnpm","install","react","lockfile","spawn"],"backgroundTag":null,"analyzedSha":"bdc96df2cb530fcdd60a7a7aabe37f610ce0f0a5","analyzedAt":"2026-08-12T22:59:56.717Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}