vercel/next.js · error

Missing ${NEXT_BIN}. Build Next.js first (pnpm --filter=next

Error message

Missing ${NEXT_BIN}. Build Next.js first (pnpm --filter=next build).

What it means

Thrown by ensureNextBuilt (benchmark.ts:290) when packages/next/dist/bin/next (NEXT_BIN) is not accessible. The render-pipeline benchmark drives that binary directly to build and start the fixture, so it must exist locally. It cannot use a globally-installed `next` because it needs the locally-built framework (the whole point is benchmarking in-tree changes).

Source

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

): 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,
  serverDied?: () => boolean
): Promise<void> {
  const start = performance.now()
  while (performance.now() - start < timeoutMs) {
    // Without this check, a server that dies on startup (e.g. EADDRINUSE
    // against a stale server on the same port) is indistinguishable from
    // a slow one — worse, a 200 from whatever else owns the port would
    // pass, and the run would silently measure the wrong server.
    if (serverDied?.()) {
      throw new Error(

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Build Next.js: `pnpm --filter=next build` (as the message says), then re-run the benchmark.
  2. On branch switch or fresh checkout, run a full bootstrap (pnpm install + pnpm build-all) per the repo's dev guide.
  3. Confirm the file exists: ls packages/next/dist/bin/next.
  4. If you intentionally only changed non-Next.js files, you still need a one-time build to produce NEXT_BIN.

Example fix

# before — error on benchmark start
#   Missing .../packages/next/dist/bin/next. Build Next.js first ...

# fix
pnpm --filter=next build
pnpm bench:render-pipeline --scenario=e2e
Defensive patterns

Strategy: validation

Validate before calling

import { accessSync, constants } from 'node:fs'
import { resolve } from 'node:path'

const NEXT_BIN = resolve(REPO_ROOT, 'packages/next/dist/bin/next')
function ensureNextBuiltOrHint() {
  try { accessSync(NEXT_BIN, constants.X_OK) }
  catch {
    throw new Error(`Missing ${NEXT_BIN}. Run: pnpm --filter=next build`)
  }
}

Type guard

import { existsSync } from 'node:fs'
function nextBinExists(bin: string): boolean {
  return existsSync(bin)
}

Try / catch

try {
  await ensureNextBuilt()
} catch (err) {
  console.error((err as Error).message)
  console.error('Run: pnpm --filter=next build   (or pnpm build-all for a full bootstrap)')
  process.exit(2)
}

Prevention

When it happens

Trigger: Calling runMinimalServerBenchmarks/runE2EBenchmarks (both call ensureNextBuilt first) when packages/next/dist/bin/next is absent — e.g. on a fresh checkout, after `git clean -fdx`, after switching branches without rebuilding, or when only a partial build ran.

Common situations: Fresh clone without bootstrap; branch switch that invalidated the dist output; `pnpm install` ran but `pnpm --filter=next build` did not; dist was deleted by a clean script.

Related errors


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