{"record":{"id":"dce40710ae11e267","repo":"thedotmack/claude-mem","slug":"worker-unavailable-on-windows-skipping-spawn-re","errorCode":null,"errorMessage":"Worker unavailable on Windows — skipping spawn (recent attempt failed within cooldown)","messagePattern":"Worker unavailable on Windows — skipping spawn \\(recent attempt failed within cooldown\\)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/services/worker-spawner.ts","lineNumber":133,"sourceCode":"    return ready ? 'ready' : 'warming';\n  }\n\n  const portInUse = await isPortInUse(port);\n  if (portInUse) {\n    logger.info('SYSTEM', 'Port in use, waiting for worker to become healthy');\n    const healthy = await waitForHealth(port, getPlatformTimeout(HOOK_TIMEOUTS.PORT_IN_USE_WAIT));\n    if (healthy) {\n      clearWorkerSpawnAttempted();\n      const ready = await waitForReadiness(port, getPlatformTimeout(HOOK_TIMEOUTS.READINESS_WAIT));\n      logger.info('SYSTEM', 'Worker is now healthy');\n      return ready ? 'ready' : 'warming';\n    }\n    logger.error('SYSTEM', 'Port in use but worker not responding to health checks');\n    return 'dead';\n  }\n\n  if (shouldSkipSpawnOnWindows()) {\n    logger.warn('SYSTEM', 'Worker unavailable on Windows — skipping spawn (recent attempt failed within cooldown)');\n    return 'dead';\n  }\n\n  // Spawn gate (src/shared/worker-spawn-gate.ts): only ONE gated launcher —\n  // hook, MCP server, or the CLI restart fallback — may spawn at a time. (The\n  // dying worker's restart handoff in worker-shutdown.ts is deliberately NOT\n  // gated: it is the primary spawner on restart, and hooks wait for its\n  // successor.) Losing the lock never fails this path; the loser skips its\n  // spawn and waits for the holder's worker. The winner holds the lock through\n  // the readiness wait and releases it in finally on every exit path.\n  const spawnLockHeld = acquireSpawnLock();\n  let spawnedPid: number | undefined;\n  try {\n    if (spawnLockHeld) {\n      logger.info('SYSTEM', 'Starting worker daemon', { workerScriptPath });\n      markWorkerSpawnAttempted();\n      spawnedPid = spawnDaemon(workerScriptPath, port);\n      if (spawnedPid === undefined) {","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/e2d1df569a8f04075d40e92461128ece7cf04c82/src/services/worker-spawner.ts#L115-L151","documentation":"On Windows, after a failed spawn attempt claude-mem writes a cooldown marker file; shouldSkipSpawnOnWindows() suppresses further spawn attempts while the marker is younger than 2 minutes (WINDOWS_SPAWN_COOLDOWN_MS). This warning fires instead of spawning and the caller gets 'dead', preventing a hook-driven spawn storm on broken setups.","triggerScenarios":"Any hook-triggered lazy spawn within 120 seconds of a previous spawn failure on Windows; the marker file's mtime is recent and no healthy worker ever appeared.","commonSituations":"Antivirus or Defender blocking the daemon executable; missing node/bun runtime; permission errors on the log or data directory; the marker left behind by an earlier unrelated failure that was since fixed.","solutions":["Check the worker log for the original spawn failure and fix it (install runtime, whitelist the daemon, fix directory permissions)","Wait at least 2 minutes for the cooldown to lapse, then retry — the marker self-heals","If certain the root cause is fixed, delete the cooldown marker file to retry immediately"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const WINDOWS_SPAWN_COOLDOWN_MS = 2 * 60 * 1000;\n\nfunction cooldownRemaining(markerPath: string): number {\n  try {\n    const mtime = fs.statSync(markerPath).mtimeMs;\n    return Math.max(0, WINDOWS_SPAWN_COOLDOWN_MS - (Date.now() - mtime));\n  } catch { return 0; }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Fix the underlying spawn failure (AV exclusions, runtime install, permissions) — the cooldown only stops the storm","On Windows, start the worker once at boot so hooks never spawn under cooldown","Wait out the 2-minute window before retrying; only delete the marker after fixing the root cause"],"tags":["windows","spawn","cooldown","worker"],"backgroundTag":"process-spawn-failure","analyzedSha":"e2d1df569a8f04075d40e92461128ece7cf04c82","analyzedAt":"2026-08-20T23:58:13.836Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}