{"record":{"id":"9f3678ae83255d8b","repo":"thedotmack/claude-mem","slug":"worker-spawned-but-readiness-endpoint-not-respondi","errorCode":null,"errorMessage":"Worker spawned but readiness endpoint not responding within window","messagePattern":"Worker spawned but readiness endpoint not responding within window","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/worker-spawner.ts","lineNumber":218,"sourceCode":"      const workerPidStillAlive = cleanStalePidFile() === 'alive';\n      const spawnedProcessStillAlive = spawnedPid !== undefined && spawnedPid > 0 && isPidAlive(spawnedPid);\n      if (!workerStillHealthy && !workerPidStillAlive && !spawnedProcessStillAlive) {\n        if (!spawnLockHeld) {\n          logger.error('SYSTEM', 'Spawn-lock holder never produced a live worker before readiness timed out');\n          return 'dead';\n        }\n        // We launched it and it is gone, so the bundle itself is the suspect —\n        // and its stderr went to a hidden window. Ask it again where we can\n        // hear the answer.\n        lastWorkerBootFailure = probeWorkerBootFailure(workerScriptPath);\n        logger.error(\n          'SYSTEM',\n          'Worker exited before readiness endpoint became available',\n          lastWorkerBootFailure ? { bootFailure: lastWorkerBootFailure } : {}\n        );\n        return 'dead';\n      }\n      logger.warn('SYSTEM', spawnLockHeld\n        ? 'Worker spawned but readiness endpoint not responding within window'\n        : 'Spawn-lock holder\\'s worker not ready within window');\n      return 'warming';\n    }\n    clearWorkerSpawnAttempted();\n    // touchPidFile is existsSync-guarded and merely refreshes the live worker's\n    // pid-file mtime — correct for lock losers too, since the worker IS up.\n    touchPidFile();\n    logger.info('SYSTEM', spawnLockHeld\n      ? 'Worker started successfully'\n      : 'Worker is up (started by another launcher)');\n    return 'ready';\n  } finally {\n    if (spawnLockHeld) releaseSpawnLock();\n  }\n}\n","sourceCodeStart":200,"sourceCodeEnd":235,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d8bc9755e74915e5c3b999181e10a67c889bce2a/src/services/worker-spawner.ts#L200-L235","documentation":"After spawning a worker while holding the spawn lock, the readiness endpoint never responded within the window and the worker did not exit. The spawner logs this variant (vs the spawn-lock-holder variant) and returns 'warming' — the process may still come up later.","triggerScenarios":"A gated spawn succeeded (process started) but waitForReadiness timed out and the worker was still alive (no 'Worker exited before readiness' boot failure logged), so the outcome is ambiguous: neither ready nor dead.","commonSituations":"Slow first boot (installing/starting Chroma, cold Bun/uv run); worker bound a different port than expected; readiness route slow because the worker is replaying session state; resource-starved CI machine.","solutions":["Poll health/readiness again after a short delay — 'warming' often resolves","Inspect worker stdout/stderr logs for slow init or port mismatch","Pre-warm the worker (start it before batch operations) to avoid cold-start latency","If the process never becomes ready, kill it and let the next attempt respawn cleanly"],"exampleFix":"// before\nif (status === 'warming') fail();\n// after\nif (status === 'warming') {\n  const ready = await waitForReadiness(port, 10000); // extended poll\n  if (ready) succeed();\n}","handlingStrategy":"retry","validationCode":"const up = await waitForHealth(port, 1000);\nconst ready = up ? await waitForReadiness(port, 15000) : false;\nif (up && !ready) console.warn('worker warming; poll again');","typeGuard":null,"tryCatchPattern":"const status = await ensureWorkerStarted(port);\nif (status === 'warming') {\n  await sleep(3000);\n  const again = await ensureWorkerStarted(port); // second chance\n}","preventionTips":["Pre-warm workers before batch jobs to avoid cold-start timeouts","Capture and inspect worker boot logs","Verify the spawned worker binds the expected port"],"tags":["worker","spawn","readiness","timeout"],"backgroundTag":"request-timeout","analyzedSha":"d8bc9755e74915e5c3b999181e10a67c889bce2a","analyzedAt":"2026-09-17T16:40:26.182Z","contentChangedAt":"2026-09-17T16:40:26.182Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}