vercel/next.js · error
Dev server did not become ready within ${timeoutMs}ms
Error message
Dev server did not become ready within ${timeoutMs}ms What it means
Thrown by waitForReady (benchmark.ts:170) when, within timeoutMs (called with 180_000 in runOnce), no probe to http://localhost:{port}/ returned a status < 500. The probe loops every 500ms and treats connection failures as 'not up yet'; only a <500 response counts as ready. So this means the dev server never produced even a provisional response in the window — it crashed, hung on first compile, or is unreachable on that host.
Source
Thrown at bench/dev-validation/benchmark.ts:170
)
})
}
async function waitForReady(port: number, timeoutMs: number): Promise<void> {
const deadline = performance.now() + timeoutMs
while (performance.now() < deadline) {
try {
const res = await fetch(`http://localhost:${port}/`)
await res.text()
if (res.status < 500) {
return
}
} catch {
// Server not up yet.
}
await sleep(500)
}
throw new Error(`Dev server did not become ready within ${timeoutMs}ms`)
}
async function stopServer(server: ChildProcess): Promise<void> {
if (server.exitCode !== null) {
return
}
const exited = new Promise<void>((resolvePromise) =>
server.once('exit', () => resolvePromise())
)
server.kill('SIGTERM')
const killed = await Promise.race([
exited.then(() => true),
sleep(5000).then(() => false),
])
if (!killed) {
server.kill('SIGKILL')
await exited
}View on GitHub (pinned to 0ae8c72462)
Solutions
- Watch the inherited stderr — the dev server's startup error prints there; the cause is usually a config/import error or EADDRINUSE.
- Confirm nothing else is on the port (lsof/ss) and that --port matches a free port.
- If first-compile is slow, raise the timeout or pre-warm; 180s should cover normal boots, so a timeout usually means a real failure.
- Run `node packages/next/dist/bin/next dev` manually in bench/dev-validation to reproduce the startup failure outside the harness.
Example fix
// before
await waitForReady(opts.port, 180_000)
// after — surface the server's own stderr so the timeout isn't a blind failure
const server = spawn('node', [NEXT_BIN, 'dev', '--port', String(opts.port)], {
cwd: APP_DIR,
stdio: ['ignore', 'inherit', 'inherit'], // stdout too, not just stderr
})
server.on('exit', (code) => {
if (code !== null) throw new Error(`dev server exited with ${code} during boot`)
})
await waitForReady(opts.port, 180_000) Defensive patterns
Strategy: validation
Validate before calling
async function portResponds(port: number): Promise<boolean> {
try {
const res = await fetch(`http://localhost:${port}/`, { signal: AbortSignal.timeout(2000) })
return res.status < 500
} catch { return false }
}
// sanity check before the long harness boot if you suspect the server itself is broken Type guard
function isTimeoutError(err: unknown): boolean {
return err instanceof Error && /did not become ready within/.test(err.message)
} Try / catch
// The dev-validation harness calls process.exit(1) on any main() rejection, so wrap
// only if you want to add diagnostics. Typically you let it fail and inspect stderr:
try {
await runOnce(worker, opts)
} catch (err) {
if (isTimeoutError(err)) {
console.error('Dev server never came up. Run `node packages/next/dist/bin/next dev` in bench/dev-validation to see the error.')
}
throw err
} Prevention
- Always inherit the spawned server's stderr (and ideally stdout) so boot failures are visible — the harness does for stderr; add stdout for faster diagnosis.
- Confirm the port is free before running (ss/lsof).
- Keep the fixture app's next.config and imports valid so dev startup doesn't crash.
- Run `next dev` manually in the fixture once to confirm it boots before trusting the harness.
When it happens
Trigger: runOnce -> waitForReady(port, 180_000) where the spawned `next dev` server: exits with an error (but the spawn uses stdio ['ignore','ignore','inherit'] so only stderr is shown), hangs during first compile (huge module graph / broken config), binds to a different interface than localhost, or the port is wrong. A server stuck returning 5xx during boot also triggers it.
Common situations: Port conflict (another process on 3210); a broken next.config / import error in the fixture app that crashes dev startup; an extremely slow first compile on a cold machine; pointing --port at a privileged/occupied port; NEXT_BIN missing so the spawned node fails immediately.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Server did not become ready within ${timeoutMs}ms
- Unknown option: --${rawKey}
- Server process exited before becoming ready (is port already
- Server did not become ready within ${timeoutMs}ms
- No artifact run found in ${requested}. Expected a results.js
AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06).
Data as JSON: /api/errors/5b3284b32f33c59a.
Report an issue: GitHub.