Summary
On Windows, when the worker's fixed port is already held by a stale/orphaned worker (common with concurrent Claude Code sessions sharing the singleton worker), every spawn attempt fails with Is port <port> in use?. The spawn cooldown then suppresses retries for ~15 minutes, during which the worker stays down. Because the hook fail-loud counter increments on every hook in that window and the default CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD is only 3, the plugin starts blocking user prompts within seconds of the worker going down and stays blocking for the whole outage.
Net effect: a transient port conflict turns into ~15 minutes of blocked prompts (claude-mem worker unreachable for N consecutive hooks.), even though the worker self-heals once the stale port holder is released.
Environment
- claude-mem: 13.6.2 (latest, installed via marketplace)
- OS: Windows 11 Pro (10.0.26200)
- Runtime: bun 1.3.13, node 24.14.1
- Claude Code CLI: v2.1.181
CLAUDE_MEM_WORKER_PORT: pinned to a fixed value in settings.json
- Multiple concurrent Claude Code sessions on the same user/machine (sharing the one singleton worker)
What I observed (log excerpts)
Outage ran ~15 minutes, from the first bind failure at 20:00:04 to recovery at 20:15:20.
[20:00:04.787] [ERROR] [SYSTEM] ✗ Worker failed to start Failed to start server. Is port 41777 in use?
[20:00:13.823] [WARN ] [SYSTEM] Worker unavailable on Windows — skipping spawn (recent attempt failed within cooldown)
[20:00:13.855] [INFO ] [SYSTEM] Another launcher holds the spawn lock — skipping lazy-spawn and waiting for its worker
[20:00:29.412] [WARN ] [SYSTEM] Spawn-lock holder's worker port did not open within the cold-boot wait (~15s)
[20:00:35.264] [ERROR] [SYSTEM] ✗ Worker failed to start Failed to start server. Is port 41777 in use?
... (repeats every ~20-40s for ~15 min) ...
[20:15:20.441] worker.pid rewritten, fresh worker bound the port successfully
The UserPromptSubmit hook surfaced: claude-mem worker unreachable for 58 consecutive hooks. and blocked the prompt.
Root cause (my read)
- The worker is a singleton on a fixed port. When a stale worker process keeps the port bound but is not answering health checks, new spawns fail at
bind.
- The Windows spawn cooldown ("recent attempt failed within cooldown") suppresses retries instead of forcing a rebind / reaping the stale holder, so the down state persists for ~15 min.
- The fail-loud threshold default of
3 is far too low relative to how often hooks fire (PostToolUse fires per tool call), so the block trips almost immediately and lasts the entire outage.
Suggested fixes
- Reap the stale port holder (or fall back to a fresh ephemeral port) when
bind fails with "port in use" and no healthy worker answers, instead of entering a long cooldown.
- Shorten or bypass the cooldown specifically for the "port in use but no healthy worker" case, since that is exactly when a fast retry/reap is needed.
- Raise the default
CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD (3 is too sensitive on Windows where transient worker restarts are common), or make the hook fail-open by default and only fail-loud after a sustained, time-based outage rather than a raw consecutive-hook count.
Workaround
Setting CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD to 30 in settings.json stops transient worker restarts from blocking prompts (memory capture just pauses and resumes when the worker recovers). Manually killing the stale worker (worker.pid) + removing supervisor.json forces a clean respawn for the rare hard hang.
Summary
On Windows, when the worker's fixed port is already held by a stale/orphaned worker (common with concurrent Claude Code sessions sharing the singleton worker), every spawn attempt fails with
Is port <port> in use?. The spawn cooldown then suppresses retries for ~15 minutes, during which the worker stays down. Because the hook fail-loud counter increments on every hook in that window and the defaultCLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLDis only3, the plugin starts blocking user prompts within seconds of the worker going down and stays blocking for the whole outage.Net effect: a transient port conflict turns into ~15 minutes of blocked prompts (
claude-mem worker unreachable for N consecutive hooks.), even though the worker self-heals once the stale port holder is released.Environment
CLAUDE_MEM_WORKER_PORT: pinned to a fixed value insettings.jsonWhat I observed (log excerpts)
Outage ran ~15 minutes, from the first bind failure at
20:00:04to recovery at20:15:20.The UserPromptSubmit hook surfaced:
claude-mem worker unreachable for 58 consecutive hooks.and blocked the prompt.Root cause (my read)
bind.3is far too low relative to how often hooks fire (PostToolUse fires per tool call), so the block trips almost immediately and lasts the entire outage.Suggested fixes
bindfails with "port in use" and no healthy worker answers, instead of entering a long cooldown.CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLD(3 is too sensitive on Windows where transient worker restarts are common), or make the hook fail-open by default and only fail-loud after a sustained, time-based outage rather than a raw consecutive-hook count.Workaround
Setting
CLAUDE_MEM_HOOK_FAIL_LOUD_THRESHOLDto30insettings.jsonstops transient worker restarts from blocking prompts (memory capture just pauses and resumes when the worker recovers). Manually killing the stale worker (worker.pid) + removingsupervisor.jsonforces a clean respawn for the rare hard hang.