{"record":{"id":"b5a0925e61a8c70e","repo":"vercel/next.js","slug":"server-did-not-become-ready-within-timeoutms-ms","errorCode":null,"errorMessage":"Server did not become ready within ${timeoutMs}ms","messagePattern":"Server did not become ready within (.+?)ms","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"bench/render-pipeline/benchmark.ts","lineNumber":321,"sourceCode":"    // Without this check, a server that dies on startup (e.g. EADDRINUSE\n    // against a stale server on the same port) is indistinguishable from\n    // a slow one — worse, a 200 from whatever else owns the port would\n    // pass, and the run would silently measure the wrong server.\n    if (serverDied?.()) {\n      throw new Error(\n        `Server process exited before becoming ready (is port already in use?)`\n      )\n    }\n    try {\n      const response = await fetch(url, { cache: 'no-store' })\n      await response.arrayBuffer()\n      if (response.ok) return\n    } catch {\n      // server not ready yet\n    }\n    await sleep(200)\n  }\n  throw new Error(`Server did not become ready within ${timeoutMs}ms`)\n}\n\nfunction spawnedServerDied(server: ReturnType<typeof spawn>): () => boolean {\n  return () => server.exitCode !== null || server.signalCode !== null\n}\n\n// The death check alone is racy on a contested port: a stale server can\n// answer the readiness probe before our child fails to bind, and the run\n// would silently measure the wrong server.\nasync function assertPortFree(port: number): Promise<void> {\n  const controller = new AbortController()\n  const timeout = setTimeout(() => controller.abort(), 1000)\n  try {\n    await fetch(`http://127.0.0.1:${port}/`, {\n      cache: 'no-store',\n      signal: controller.signal,\n    })\n  } catch {","sourceCodeStart":303,"sourceCodeEnd":339,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/bench/render-pipeline/benchmark.ts#L303-L339","documentation":"Thrown by waitForServerReady (benchmark.ts:321) when the readiness loop exhausts timeoutMs (default 30000 via --timeout-ms) without the server returning response.ok, and crucially without the child having exited (that's error [14]). So the process is alive but never served a healthy 200 — it's hung in boot, slow to compile, or stuck returning non-2xx/non-5xx (e.g. endless redirects) that never satisfy response.ok.","triggerScenarios":"The spawned server stays alive but never answers 2xx within --timeout-ms: extremely slow first compile/build output load, a server stuck in a boot loop that doesn't crash, returning 3xx/4xx forever, or a route that 404s on the probe URL (the probe hits the first route in routeSubset.routes, so a bad first route can keep failing).","commonSituations":"First route in --routes doesn't exist on the server (probe 404s indefinitely); very slow disk/CPU making boot exceed 30s; the server is up but misconfigured to never return 200 on the probe path.","solutions":["Raise --timeout-ms if boot is legitimately slow (e.g. --timeout-ms=120000).","Ensure the first route in --routes exists and returns 200 — the readiness probe uses routes[0] (benchmark.ts:766, 893).","Check the server isn't stuck returning redirects/404s by curling the probe URL directly.","Reproduce by running the server command manually and timing the first 200."],"exampleFix":"# before — probe hits a missing first route, never 200s\n#   pnpm bench:render-pipeline --routes=/nope,/dashboard\n\n# after — first route exists, and bump the boot timeout if needed\n#   pnpm bench:render-pipeline --routes=/dashboard,/blog --timeout-ms=60000","handlingStrategy":"validation","validationCode":"// confirm the first route returns 200 before the long boot probe depends on it\nasync function firstRouteOk(base: string, firstRoute: string): Promise<boolean> {\n  try {\n    const res = await fetch(`${base}${firstRoute}`, { signal: AbortSignal.timeout(2000) })\n    return res.ok\n  } catch { return false }\n}","typeGuard":"function isReadinessTimeout(err: unknown): boolean {\n  return err instanceof Error && /Server did not become ready within/.test(err.message)\n}","tryCatchPattern":"try {\n  await waitForServerReady(url, timeoutMs, serverDied)\n} catch (err) {\n  if (isReadinessTimeout(err) && !isServerDiedError(err)) {\n    console.error(`Server alive but never returned 200 within ${timeoutMs}ms. Probe URL: ${url}. Raise --timeout-ms or check the first route.`)\n  }\n  throw err\n}","preventionTips":["Make the FIRST route in --routes a fast 200 path — the readiness probe uses routes[0].","Raise --timeout-ms for legitimately slow boots (large fixture, cold disk).","curl the probe URL directly to see what the server actually returns.","Distinguish this (process alive, never 200) from error [14] (process exited) before diagnosing."],"tags":["server","timeout","render-pipeline","startup","benchmark","readiness"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}