pnpm/pnpm · error · PnpmError

ERR_PNPM_SCRIPT_NAME_IS_REQUIRED

ERR_PNPM_SCRIPT_NAME_IS_REQUIRED

Error message

You must specify the script you want to run

What it means

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.

Source

Thrown at pnpm11/exec/commands/src/runRecursive.ts:58

> & Pick<ConfigContext, 'rootProjectManifest' | 'allProjectsGraph' | 'prodAllProjectsGraph' | 'prodOnlySelectedProjectDirs'> & Required<Pick<ConfigContext, 'allProjects' | 'selectedProjectsGraph'> & Pick<Config, 'workspaceDir' | 'dir'>> &
Partial<Pick<Config, 'extraBinPaths' | 'extraEnv' | 'bail' | 'reporter' | 'reverse' | 'sort' | 'workspaceConcurrency'>> &
{
  ifPresent?: boolean
  resumeFrom?: string
  reportSummary?: boolean
  sequential?: boolean
}

export async function runRecursive (
  params: string[],
  opts: RecursiveRunOpts
): Promise<void> {
  if (opts.sequential) {
    opts.workspaceConcurrency = 1
  }
  const [scriptName, ...passedThruArgs] = params
  if (!scriptName) {
    throw new PnpmError('SCRIPT_NAME_IS_REQUIRED', 'You must specify the script you want to run')
  }
  let hasCommand = 0

  const sortedPackageChunks = opts.sort
    ? sortFilteredProjects(opts)
    : [(Object.keys(opts.selectedProjectsGraph) as ProjectRootDir[]).sort()]
  let packageChunks: ProjectRootDir[][] = opts.reverse ? sortedPackageChunks.reverse() : sortedPackageChunks

  if (opts.resumeFrom) {
    packageChunks = getResumedPackageChunks({
      resumeFrom: opts.resumeFrom,
      chunks: packageChunks,
      selectedProjectsGraph: opts.selectedProjectsGraph,
    })
  }

  const limitRun = pLimit(getWorkspaceConcurrency(opts.workspaceConcurrency))
  const stdio =

View on GitHub (pinned to 6261b7f388)

Solutions

  1. Pass the script name: `pnpm -r run build`
  2. Guard CI/shell variables: `pnpm -r run "${SCRIPT:?SCRIPT not set}"`
  3. If emptiness is legitimate, handle it before invoking pnpm rather than relying on the error

Example fix

# before
pnpm -r run "$SCRIPT"   # SCRIPT unset -> ERR_PNPM_SCRIPT_NAME_IS_REQUIRED

# after
pnpm -r run "${SCRIPT:?SCRIPT not set}"
Defensive patterns

Strategy: validation

Validate before calling

if (params.length < 1 || !params[0]) {
  fail('usage: pnpm -r run <script> [-- <args>...]')
}

Type guard

function hasScriptName (params: string[]): params is [scriptName: string, ...args: string[]] {
  return params.length > 0 && typeof params[0] === 'string' && params[0].length > 0
}

Try / catch

try {
  await runRecursive(params, opts)
} catch (err) {
  if (err instanceof PnpmError && err.code === 'ERR_PNPM_SCRIPT_NAME_IS_REQUIRED') {
    return failUsage('script name missing')
  }
  throw err
}

Prevention

When it happens

Trigger: `pnpm -r run` with no argument, `pnpm recursive run --parallel` (flags but no script name), or a programmatic runRecursive([]) call.

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of pnpm/pnpm@6261b7f388 (2026-08-17). Data as JSON: /api/errors/6060016c8af8f180. Report an issue: GitHub.