thedotmack/claude-mem · warning
Worker is alive but readiness timed out — proceeding anyway
Error message
Worker is alive but readiness timed out — proceeding anyway
What it means
The worker is already running and passes the health check, but its readiness endpoint did not respond within READINESS_WAIT. The spawner treats this as non-fatal: it logs 'Worker already running and healthy' and returns 'warming' so callers can proceed or retry later.
Solutions
- Treat 'warming' as acceptable and retry the request shortly
- Restart the worker so versions align (CLI restart / delete pid file)
- Increase READINESS_WAIT timeout on slow machines
- Confirm worker version matches the CLI to ensure the readiness route exists
Example fix
// before const status = await ensureWorkerStarted(port); if (status !== 'ready') return; // after const status = await ensureWorkerStarted(port); if (status === 'warming') return; // health OK; readiness will follow — proceed optimistically
Defensive patterns
Strategy: retry
Validate before calling
const healthy = await waitForHealth(port, 1000);
if (!healthy) throw new Error('worker not healthy at all'); // distinct from warming
const ready = await fetch(`http://localhost:${port}/readiness`).then(r => r.ok).catch(() => false); Try / catch
const status = await ensureWorkerStarted(port);
if (status === 'warming') {
// health passed; poll readiness a bit longer before giving up
const ready = await waitForReadiness(port, 5000);
} Prevention
- Keep CLI and worker versions in sync so the readiness route exists
- Increase READINESS_WAIT on slow platforms
- Poll readiness once more before declaring failure on 'warming'
When it happens
Trigger: waitForHealth(port, 1000) succeeds (worker up) but waitForReadiness(port, getPlatformTimeout(READINESS_WAIT)) returns false — readiness endpoint slow, not yet implemented, or the worker is up but still loading models/session state.
Common situations: Version skew: older worker binary lacking the readiness route while health exists; heavy init (Chroma startup) delaying readiness; transient network/socket hiccup on localhost; very short platform timeout.
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
- Live PID detected but worker did not become ready before…
- 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/d757c23e941c8e8f.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/worker-spawner.ts:127
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) {
clearWorkerSpawnAttempted();
const ready = await waitForReadiness(port, getPlatformTimeout(HOOK_TIMEOUTS.READINESS_WAIT));
logger.info('SYSTEM', 'Worker is now healthy');
return ready ? 'ready' : 'warming';
}
// The port is bound but nothing answers health. Usually this is a dead
// worker whose surviving chroma sidecar chain (uvx -> uv -> python) holds
// the inherited listening socket — a ghost listener under a dead PIDView on GitHub (pinned to d8bc9755e7)