thedotmack/claude-mem · error
Worker lazy-spawned but did not become ready before hook rea
Error message
Worker lazy-spawned but did not become ready before hook readiness timeout
What it means
The worker's port opened (it is alive) but waitForWorkerReadiness timed out before the ready flag flipped — readiness additionally requires the health endpoint to report the worker fully initialized. The hook returns false and skips its API call, degrading that hook event.
Source
Thrown at src/shared/worker-utils.ts:604
// `start` hook is booting the daemon in parallel, and a cold macOS+Chroma
// worker needs ~7s to bind. The old 3-attempt/250ms budget (~0.75s) expired
// long before that, so the context (and session-init) hooks raced boot and
// soft-failed to empty — dropping memory injection and the user_prompts row
// (the upstream trigger for #2794). Wait up to ~15.5s (≈ POST_SPAWN_WAIT) so
// whichever worker wins the port is seen before we give up.
const alive = await waitForWorkerPort({ attempts: 6, backoffMs: 500 });
if (!alive) {
logger.warn('SYSTEM', spawnLockHeld
? 'Worker port did not open after lazy-spawn within the cold-boot wait (~15s)'
: 'Spawn-lock holder\'s worker port did not open within the cold-boot wait (~15s)');
return false;
}
} finally {
if (spawnLockHeld) releaseSpawnLock();
}
const ready = await waitForWorkerReadiness();
if (!ready) {
logger.warn('SYSTEM', 'Worker lazy-spawned but did not become ready before hook readiness timeout');
return false;
}
// Amplifier guard: even if the worker that won the port is still stale,
// never recycle a second time in the same hook invocation.
if (expectedPluginVersion !== null) {
await warnIfVersionStillMismatched(expectedPluginVersion);
}
return true;
}
let aliveCache: boolean | null = null;
export async function ensureWorkerAliveOnce(): Promise<boolean> {
if (aliveCache !== null) return aliveCache;
aliveCache = await ensureWorkerRunning();
return aliveCache;
}
View on GitHub (pinned to e2d1df569a)
Solutions
- Wait and retry — the next hook event usually finds the worker ready; send the next prompt.
- Raise the readiness budget via CLAUDE_MEM_HEALTH_TIMEOUT_MS or the corresponding settings key (bounded; see readTimeoutEnv).
- Inspect worker logs for the long-running init step and fix that (e.g., pre-download embedding models).
- Pre-warm the worker at login so sessions never race initialization.
Example fix
# before export CLAUDE_MEM_HEALTH_TIMEOUT_MS=2000 # too short for cold Chroma boot # after export CLAUDE_MEM_HEALTH_TIMEOUT_MS=20000 # within the 500..300000 bounds
Defensive patterns
Strategy: retry
Validate before calling
const ready = await waitForWorkerReadiness();
if (!ready) {
// port is open but init incomplete — skip this event, retry next
return false;
} Type guard
const isWorkerReady = async (): Promise<boolean> => {
try { return (await fetchWorkerHealth()).ready === true; }
catch { return false; }
}; Prevention
- Budget the readiness timeout for your worst cold boot, not your average one.
- Pre-warm the worker at login; first-run Chroma downloads are the usual slow step.
- After a claude-mem upgrade, open one warm-up session before relying on memory injection.
When it happens
Trigger: Worker bound its port but is still initializing (Chroma connect, embeddings setup, DB migrations, session store warm-up) past the readiness budget.
Common situations: First-run Chroma embedding model download; a large migration after upgrade; slow or busy disks stretching init past the timeout.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Worker is healthy but not ready; skipping hook API call
- Worker port did not open after lazy-spawn within the cold-bo
- Live PID detected but worker did not become ready before tim
- Worker spawned but readiness endpoint not responding within
- Spawn-lock holder's worker port did not open within the cold
AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20).
Data as JSON: /api/errors/4b24c09a3b077006.
Report an issue: GitHub.