thedotmack/claude-mem · warning

Worker spawned but readiness endpoint not responding within

Error message

Worker spawned but readiness endpoint not responding within window

What it means

After this launcher spawned a worker, /readiness did not respond within the window (~30s platform-adjusted), but the health endpoint, PID file, or spawned process is still alive — so the worker did start, it is just not fully initialized. The spawner logs this (the spawn-lock-holder variant) and returns 'warming' instead of failing.

Source

Thrown at src/services/worker-spawner.ts:171

        return 'dead';
      }
    } else {
      logger.info('SYSTEM', 'Another launcher holds the spawn lock — skipping duplicate spawn and waiting for its worker');
    }

    const ready = await waitForReadiness(port, getPlatformTimeout(HOOK_TIMEOUTS.READINESS_WAIT));
    if (!ready) {
      const workerStillHealthy = await waitForHealth(port, 1000);
      const workerPidStillAlive = cleanStalePidFile() === 'alive';
      const spawnedProcessStillAlive = spawnedPid !== undefined && spawnedPid > 0 && isPidAlive(spawnedPid);
      if (!workerStillHealthy && !workerPidStillAlive && !spawnedProcessStillAlive) {
        logger.error('SYSTEM', spawnLockHeld
          ? 'Worker exited before readiness endpoint became available'
          : 'Spawn-lock holder never produced a live worker before readiness timed out');
        return 'dead';
      }
      logger.warn('SYSTEM', spawnLockHeld
        ? 'Worker spawned but readiness endpoint not responding within window'
        : 'Spawn-lock holder\'s worker not ready within window');
      return 'warming';
    }
    clearWorkerSpawnAttempted();
    // touchPidFile is existsSync-guarded and merely refreshes the live worker's
    // pid-file mtime — correct for lock losers too, since the worker IS up.
    touchPidFile();
    logger.info('SYSTEM', spawnLockHeld
      ? 'Worker started successfully'
      : 'Worker is up (started by another launcher)');
    return 'ready';
  } finally {
    if (spawnLockHeld) releaseSpawnLock();
  }
}

View on GitHub (pinned to e2d1df569a)

Solutions

  1. Wait for readiness: poll GET /readiness or run `claude-mem status` again after a minute
  2. Check worker logs for which init step is slow or stuck (dependency preflight warnings appear above this one)
  3. If it happens on every start, trim the search index/backlog or extend the platform timeout
Defensive patterns

Strategy: retry

Validate before calling

async function waitReadyAfterSpawn(port: number, timeoutMs = 60000): Promise<boolean> {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    try { if (await fetch(`http://127.0.0.1:${port}/readiness`).then(r => r.ok)) return true; } catch {}
    await new Promise(r => setTimeout(r, 1000));
  }
  return false;
}

Prevention

When it happens

Trigger: Spawn succeeded but DB/search initialization exceeds READINESS_WAIT: first-run dependency setup, large migrations, or heavy load during startup.

Common situations: Cold starts after install or upgrade; machines with slow disks; concurrent claude-mem hooks triggering while init runs.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/9f3678ae83255d8b. Report an issue: GitHub.