{"id":"027cd31ca72c4181","repo":"nestjs/nest","slug":"server-did-not-become-ready-in-timeoutms-ms-u","errorCode":null,"errorMessage":"Server did not become ready in ${timeoutMs}ms: ${url}","messagePattern":"Server did not become ready in (.+?)ms: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"tools/benchmarks/src/main.ts","lineNumber":137,"sourceCode":"  const hasFetch = typeof (globalThis as any).fetch === 'function';\n\n  while (Date.now() - start < timeoutMs) {\n    try {\n      if (hasFetch) {\n        const res = await (globalThis as any).fetch(url, { method: 'GET' });\n        if (res && (res.status === 200 || res.status === 404)) return;\n      } else {\n        // best-effort fallback\n        await sleep(250);\n        return;\n      }\n    } catch {\n      // server not ready yet\n    }\n    await sleep(100);\n  }\n\n  throw new Error(`Server did not become ready in ${timeoutMs}ms: ${url}`);\n}\n\nfunction killChild(child: ChildProcess): void {\n  if (!child || child.killed) return;\n\n  // Try graceful termination first.\n  try {\n    child.kill('SIGTERM');\n  } catch {\n    // ignore\n  }\n\n  // Force kill if still alive shortly after.\n  setTimeout(() => {\n    try {\n      if (!child.killed) child.kill('SIGKILL');\n    } catch {\n      // ignore","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/nestjs/nest/blob/6ec0e2783d15290732447f304d8549b591b9749e/tools/benchmarks/src/main.ts#L119-L155","documentation":"An internal readiness guard in the benchmarks CLI (tools/benchmarks/src/main.ts:137). runOne forks a framework server (express/fastify/nest-express/nest-fastify) as a child process, then waitForServer polls the target URL with global fetch every 100ms; if it never returns 200 or 404 within timeoutMs (default 5000), it throws a plain Error with this message, aborting the whole benchmark run. Because the child is forked with stdio:'ignore', the underlying startup error is hidden — the timeout is the only symptom.","triggerScenarios":"Running `npm run benchmarks` when the forked framework process crashes on boot, binds the wrong port, or never listens — e.g., port 3000 already in use, missing compiled bundle at the forked entry path, framework built for an incompatible Node version, or a slow CI box exceeding the 5s budget.","commonSituations":"Another dev server already occupying :3000; dist/ not built (node resolves a path with no compiled JS); framework entry file path changed after a refactor; child crashes synchronously on import but stdio:'ignore' swallows it; CI runner under load.","solutions":["Free port 3000 (lsof/iOSTAT or pick --port) before running the benchmark.","Build the framework bundles first so fork() resolves a real entry file.","Temporarily change stdio from 'ignore' to 'inherit' to see the child's startup error.","Raise the timeout (waitForServer(url, 15_000)) on slow machines, and surface child stderr in the thrown message."],"exampleFix":"// before\nconst child = fork(frameworkEntry(framework), { stdio: 'ignore' });\n...\nthrow new Error(`Server did not become ready in ${timeoutMs}ms: ${url}`);\n\n// after\nconst child = fork(frameworkEntry(framework), { stdio: 'inherit' });\nchild.stderr?.on('data', d => console.error(`[${framework}]`, d.toString()));\nawait waitForServer(url, 15_000);","handlingStrategy":"retry","validationCode":"// Before running, ensure the port is free and the bundle is built.\nimport { createServer } from 'node:net';\n\nasync function isPortFree(port: number): Promise<boolean> {\n  return new Promise(resolve => {\n    const tester = createServer();\n    tester.once('error', () => resolve(false));\n    tester.once('listening', () => tester.close(() => resolve(true)));\n    tester.listen(port);\n  });\n}\n\nif (!(await isPortFree(args.port))) {\n  throw new Error(`port ${args.port} is already in use`);\n}","typeGuard":"function isChildError(e: unknown, codes: string[]): boolean {\n  return typeof e === 'object' && e !== null\n    && codes.includes((e as NodeJS.ErrnoException).code ?? '');\n}","tryCatchPattern":"try {\n  await runOne(framework, args);\n} catch (e) {\n  if (e instanceof Error && /did not become ready/.test(e.message)) {\n    // inspect child stderr (switch stdio to 'inherit'), free the port, or raise timeout\n    console.error('startup failed — re-run with stdio: inherit');\n  }\n  throw e;\n}","preventionTips":["Check the port is free before forking.","Build framework bundles before running so fork() resolves a real entry file.","Run child with stdio 'inherit' during local debugging to see startup errors.","Make the readiness timeout configurable and surface child stderr in the thrown message."],"tags":["benchmark","tooling","timeout","child-process","node"],"analyzedSha":"6ec0e2783d15290732447f304d8549b591b9749e","analyzedAt":"2026-08-03T17:42:23.673Z","schemaVersion":2}