thedotmack/claude-mem · warning
Live PID detected but worker did not become ready before…
Error message
Live PID detected but worker did not become ready before timeout
What it means
ensureWorkerStarted detected a live PID (pid file says the process is alive) but the worker never served its readiness endpoint before the wait timed out. After a final health+PID recheck, it classifies the worker as 'warming' — alive but not yet usable — rather than dead.
Solutions
- Wait and retry — the worker may finish warming and become ready
- Check worker logs for boot errors or hangs during initialization
- Kill the stuck process (delete pid file) and trigger a fresh spawn
- Verify CLI and worker versions match (version is logged on verified handoff)
Example fix
// before
const status = await ensureWorkerStarted(port);
if (status === 'warming') throw new Error('worker not ready');
// after
let status = await ensureWorkerStarted(port);
if (status === 'warming') {
await sleep(2000);
status = await ensureWorkerStarted(port); // retry once after warming
} Defensive patterns
Strategy: retry
Validate before calling
const pidAlive = cleanStalePidFile() === 'alive';
if (pidAlive) console.log('worker pid alive; allow extra readiness time before retry'); Try / catch
async function waitUntilReady(port, attempts = 3) {
for (let i = 0; i < attempts; i++) {
const s = await ensureWorkerStarted(port);
if (s === 'ready') return true;
await sleep(2000);
}
return false;
} Prevention
- Retry with backoff when status is 'warming'
- Pre-warm the worker before latency-sensitive operations
- Check worker logs when readiness repeatedly times out
- Delete stale pid files before forced respawns
When it happens
Trigger: A worker process exists (cleanStalePidFile() === 'alive') but waitForReadiness timed out; a last-chance waitForHealth(port, 1000) also fails, yet the PID still lives, so the code logs this warning and returns 'warming'.
Common situations: Worker booted but is stuck initializing (slow Chroma/Python startup via uv); readiness route not yet registered during a version mismatch between CLI and worker; process alive but wedged; slow cold start on Windows.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Worker is alive but readiness timed out — proceeding anyway
- Worker is healthy but not ready; skipping hook API call
- Worker lazy-spawned but did not become ready before hook…
- Worker spawned but readiness endpoint not responding within…
- Graceful shutdown deadline exceeded — proceeding
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/08088a7293c48048.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/worker-spawner.ts:119
return 'dead';
}
const pidFileStatus = cleanStalePidFile();
if (pidFileStatus === 'alive') {
logger.info('SYSTEM', 'Worker PID file points to a live process, skipping duplicate spawn');
const ready = await waitForReadiness(port, getPlatformTimeout(HOOK_TIMEOUTS.READINESS_WAIT));
if (ready) {
clearWorkerSpawnAttempted();
logger.info('SYSTEM', 'Worker became ready while waiting on live PID');
return 'ready';
}
const workerStillHealthy = await waitForHealth(port, 1000);
const workerPidStillAlive = cleanStalePidFile() === 'alive';
if (!workerStillHealthy && !workerPidStillAlive) {
logger.error('SYSTEM', 'Live PID disappeared before readiness endpoint became available');
return 'dead';
}
logger.warn('SYSTEM', 'Live PID detected but worker did not become ready before timeout');
return 'warming';
}
if (await waitForHealth(port, 1000)) {
clearWorkerSpawnAttempted();
const ready = await waitForReadiness(port, getPlatformTimeout(HOOK_TIMEOUTS.READINESS_WAIT));
if (!ready) {
logger.warn('SYSTEM', 'Worker is alive but readiness timed out — proceeding anyway');
}
logger.info('SYSTEM', 'Worker already running and healthy');
return ready ? 'ready' : 'warming';
}
const portInUse = await isPortInUse(port);
if (portInUse) {
logger.info('SYSTEM', 'Port in use, waiting for worker to become healthy');
const healthy = await waitForHealth(port, getPlatformTimeout(HOOK_TIMEOUTS.PORT_IN_USE_WAIT));
if (healthy) {View on GitHub (pinned to d8bc9755e7)