{"record":{"id":"6060016c8af8f180","repo":"pnpm/pnpm","slug":"err-pnpm-script-name-is-required","errorCode":"ERR_PNPM_SCRIPT_NAME_IS_REQUIRED","errorMessage":"You must specify the script you want to run","messagePattern":"You must specify the script you want to run","errorType":"exception","errorClass":"PnpmError","httpStatus":null,"severity":"error","filePath":"pnpm11/exec/commands/src/runRecursive.ts","lineNumber":58,"sourceCode":"> & Pick<ConfigContext, 'rootProjectManifest' | 'allProjectsGraph' | 'prodAllProjectsGraph' | 'prodOnlySelectedProjectDirs'> & Required<Pick<ConfigContext, 'allProjects' | 'selectedProjectsGraph'> & Pick<Config, 'workspaceDir' | 'dir'>> &\nPartial<Pick<Config, 'extraBinPaths' | 'extraEnv' | 'bail' | 'reporter' | 'reverse' | 'sort' | 'workspaceConcurrency'>> &\n{\n  ifPresent?: boolean\n  resumeFrom?: string\n  reportSummary?: boolean\n  sequential?: boolean\n}\n\nexport async function runRecursive (\n  params: string[],\n  opts: RecursiveRunOpts\n): Promise<void> {\n  if (opts.sequential) {\n    opts.workspaceConcurrency = 1\n  }\n  const [scriptName, ...passedThruArgs] = params\n  if (!scriptName) {\n    throw new PnpmError('SCRIPT_NAME_IS_REQUIRED', 'You must specify the script you want to run')\n  }\n  let hasCommand = 0\n\n  const sortedPackageChunks = opts.sort\n    ? sortFilteredProjects(opts)\n    : [(Object.keys(opts.selectedProjectsGraph) as ProjectRootDir[]).sort()]\n  let packageChunks: ProjectRootDir[][] = opts.reverse ? sortedPackageChunks.reverse() : sortedPackageChunks\n\n  if (opts.resumeFrom) {\n    packageChunks = getResumedPackageChunks({\n      resumeFrom: opts.resumeFrom,\n      chunks: packageChunks,\n      selectedProjectsGraph: opts.selectedProjectsGraph,\n    })\n  }\n\n  const limitRun = pLimit(getWorkspaceConcurrency(opts.workspaceConcurrency))\n  const stdio =","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/pnpm/pnpm/blob/6261b7f388016d57ca6b90340342411cd1d0d00f/pnpm11/exec/commands/src/runRecursive.ts#L40-L76","documentation":"The recursive runner requires the script name as its first parameter. runRecursive destructures [scriptName, ...passedThruArgs] from params and throws SCRIPT_NAME_IS_REQUIRED when that first element is missing — nothing has been selected to run in any package.","triggerScenarios":"`pnpm -r run` with no argument, `pnpm recursive run --parallel` (flags but no script name), or a programmatic runRecursive([]) call.","commonSituations":"Shell scripts forwarding an unset variable: `pnpm -r run \"$SCRIPT\"` with SCRIPT empty. CI templates where the script slot is left blank. Autocompletion inserting only flags.","solutions":["Pass the script name: `pnpm -r run build`","Guard CI/shell variables: `pnpm -r run \"${SCRIPT:?SCRIPT not set}\"`","If emptiness is legitimate, handle it before invoking pnpm rather than relying on the error"],"exampleFix":"# before\npnpm -r run \"$SCRIPT\"   # SCRIPT unset -> ERR_PNPM_SCRIPT_NAME_IS_REQUIRED\n\n# after\npnpm -r run \"${SCRIPT:?SCRIPT not set}\"","handlingStrategy":"validation","validationCode":"if (params.length < 1 || !params[0]) {\n  fail('usage: pnpm -r run <script> [-- <args>...]')\n}","typeGuard":"function hasScriptName (params: string[]): params is [scriptName: string, ...args: string[]] {\n  return params.length > 0 && typeof params[0] === 'string' && params[0].length > 0\n}","tryCatchPattern":"try {\n  await runRecursive(params, opts)\n} catch (err) {\n  if (err instanceof PnpmError && err.code === 'ERR_PNPM_SCRIPT_NAME_IS_REQUIRED') {\n    return failUsage('script name missing')\n  }\n  throw err\n}","preventionTips":["In shell wrappers, expand variables as \"${SCRIPT:?SCRIPT not set}\" so emptiness fails loudly","Validate CI templates that interpolate the script name before shipping them"],"tags":["scripts","recursive","argument-validation","cli"],"backgroundTag":"missing-required-argument","analyzedSha":"6261b7f388016d57ca6b90340342411cd1d0d00f","analyzedAt":"2026-08-17T18:30:54.750Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}