vercel/next.js · error

Port ${port} is already serving responses — another server i

Error message

Port ${port} is already serving responses — another server is running. Stop it, pass a different --port, or use --start-server=false to trace against it deliberately.

What it means

Thrown by assertPortFree before starting a server when an HTTP GET to http://127.0.0.1:{port}/ already returns a response. This prevents the contested-port race where a stale server answers the readiness probe while the new child fails to bind, causing the tracer to silently measure the wrong (old) server. The error message offers three explicit escapes.

Source

Thrown at bench/render-pipeline/client-trace.ts:266

}

// The death check alone is racy on a contested port: a stale server can
// answer the readiness probe before our child fails to bind, and the run
// would silently measure the wrong server.
async function assertPortFree(port: number): Promise<void> {
  const controller = new AbortController()
  const timeout = setTimeout(() => controller.abort(), 1000)
  try {
    await fetch(`http://127.0.0.1:${port}/`, {
      cache: 'no-store',
      signal: controller.signal,
    })
  } catch {
    return
  } finally {
    clearTimeout(timeout)
  }
  throw new Error(
    `Port ${port} is already serving responses — another server is running. ` +
      `Stop it, pass a different --port, or use --start-server=false to ` +
      `trace against it deliberately.`
  )
}

async function gracefulKill(server: ReturnType<typeof spawn>) {
  // once('exit') never resolves for a child that already exited.
  if (server.exitCode !== null || server.signalCode !== null) return
  const tryKill = async (signal: NodeJS.Signals, timeoutMs: number) => {
    server.kill(signal)
    const didExit = await Promise.race([
      once(server, 'exit')
        .then(() => true)
        .catch(() => true),
      sleep(timeoutMs).then(() => false),
    ])
    return didExit

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Stop the existing server: lsof -ti:PORT | xargs kill, or close the dev terminal.
  2. Pass a different --port that is free.
  3. Pass --start-server=false to deliberately trace against the already-running server (you accept it is the target).

Example fix

# before: port busy, ambiguous target
pnpm bench:render-pipeline:client --port=3199

# after: free the port first
lsof -ti:3199 | xargs kill -9
pnpm bench:render-pipeline:client --port=3199
Defensive patterns

Strategy: validation

Validate before calling

// Reuse the tracer's own logic: if something answers, decide deliberately
async function portHasServer(port: number): Promise<boolean> {
  try {
    await fetch(`http://127.0.0.1:${port}/`, { signal: AbortSignal.timeout(1000) })
    return true
  } catch { return false }
}
if (await portHasServer(port) && !options.attachToExisting) {
  throw new Error(`Stop the server on ${port} or pass a different --port`)
}

Type guard

null

Try / catch

null

Prevention

When it happens

Trigger: A previous next dev/start (or any HTTP server) is still bound to the port; a different benchmark left a process running; an unrelated dev server (Vite, Express) occupies the port.

Common situations: Iterating on benchmarks without killing the prior server; a crashed benchmark left an orphan server; running multiple trace jobs concurrently on the default port.

Related errors


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