vercel/next.js · error

Command failed: ${command} ${args.join(' ')} (exit ${code})

Error message

Command failed: ${command} ${args.join(' ')} (exit ${code})

What it means

Thrown by runCommand (benchmark.ts:280) when a spawned subprocess (the generate-client-graph script, `next build`, or other node invocations via runCommand) exits with a non-zero code. The message includes the command, its args, and the exit code. The subprocess inherits stdio so its own error output appears above this throw, making the exit cause visible.

Source

Thrown at bench/render-pipeline/benchmark.ts:280

  const stddev = Math.sqrt(variance)
  const p95 = sorted[Math.max(0, Math.ceil(sorted.length * 0.95) - 1)]
  return { min, median, mean, stddev, p95, max }
}

async function runCommand(
  command: string,
  args: string[],
  cwd: string,
  env: NodeJS.ProcessEnv = process.env
): Promise<void> {
  const child = spawn(command, args, {
    cwd,
    env,
    stdio: 'inherit',
  })
  const [code] = (await once(child, 'exit')) as [number | null]
  if (code !== 0) {
    throw new Error(
      `Command failed: ${command} ${args.join(' ')} (exit ${code})`
    )
  }
}

async function ensureNextBuilt() {
  try {
    await access(NEXT_BIN)
  } catch {
    throw new Error(
      `Missing ${NEXT_BIN}. Build Next.js first (pnpm --filter=next build).`
    )
  }
}

async function waitForServerReady(
  url: string,
  timeoutMs: number,

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Scroll up: the subprocess printed the real error (build error, missing module, etc.) to stdout/stderr before this throw — fix that.
  2. Reproduce manually: run the exact command + args from the message in the same cwd.
  3. If it's `next build`, ensure NEXT_BIN exists (pnpm --filter=next build) and the basic-app fixture is in sync with current Next.js.
  4. If it's the generator, run `node bench/basic-app/scripts/generate-client-graph.mjs` by hand to see the failure.

Example fix

# before — opaque failure
#   Error: Command failed: node [...]/generate-client-graph.mjs (exit 1)

# reproduce to find the real cause
node bench/basic-app/scripts/generate-client-graph.mjs
# then fix the script/app, then re-run the benchmark
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight the things runCommand will invoke:
import { existsSync } from 'node:fs'
if (!existsSync(NEXT_BIN)) throw new Error('NEXT_BIN missing — build first')
if (!existsSync(resolve(options.appDir, 'scripts/generate-client-graph.mjs'))) {/* optional generator */}
// for next build, you can dry-check the fixture compiles via `next build` manually first

Type guard

function isCommandFailure(err: unknown): err is Error {
  return err instanceof Error && err.message.startsWith('Command failed:')
}

Try / catch

try {
  await runCommand('node', [NEXT_BIN, 'build'], options.appDir, env)
} catch (err) {
  if (isCommandFailure(err)) {
    // the subprocess already printed its error to inherited stdio; just annotate
    console.error('\nThe command above exited non-zero. See its output above for the cause.')
  }
  throw err
}

Prevention

When it happens

Trigger: ensureGeneratedClientGraph running scripts/generate-client-graph.mjs that exits non-zero; `next build` failing on the basic-app fixture (build error in the app); any other runCommand call. Because stdio is 'inherit', the real failure text scrolls by before this error.

Common situations: A broken fixture app that fails to build; the client-graph generator script has a bug or hits a missing dependency; a Next.js source change that breaks the basic-app build; running against an unbuilt NEXT_BIN so `next build` itself errors.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/063453f605417cc3. Report an issue: GitHub.