thedotmack/claude-mem · error
Hard cap exceeded: ${activeCount} processes in registry (cap
Error message
Hard cap exceeded: ${activeCount} processes in registry (cap=${TOTAL_PROCESS_HARD_CAP}). Refusing to spawn more. What it means
Error "Hard cap exceeded: ${activeCount} processes in registry (cap=${TOTAL_PROCESS_HARD_CAP}). Refusing to spawn more." thrown in thedotmack/claude-mem.
Source
Thrown at src/supervisor/process-registry.ts:549
function notifySlotAvailable(): void {
const waiter = slotWaiters.shift();
if (waiter) waiter();
}
/**
* Waits until an SDK agent slot is free, then reserves it. The count check
* and the reservation happen in the same synchronous block, so no concurrent
* caller can be granted the same slot. The caller must release the returned
* reservation once the spawned process is registered (the registry record
* takes over the accounting) or when the spawn fails or never happens:
* a leaked reservation would occupy the slot until the worker restarts.
*/
export async function waitForSlot(maxConcurrent: number, signal?: AbortSignal): Promise<SlotReservation> {
getProcessRegistry().pruneDeadEntries();
const activeCount = getActiveSdkCount();
if (activeCount >= TOTAL_PROCESS_HARD_CAP) {
throw new Error(`Hard cap exceeded: ${activeCount} processes in registry (cap=${TOTAL_PROCESS_HARD_CAP}). Refusing to spawn more.`);
}
if (activeCount < maxConcurrent) return takeSlotReservation();
if (signal?.aborted) {
throw new Error('waitForSlot aborted before queuing');
}
logger.info('PROCESS', `Pool limit reached (${activeCount}/${maxConcurrent}), waiting for slot...`);
return new Promise<SlotReservation>((resolve, reject) => {
let recheckTimer: ReturnType<typeof setInterval> | null = null;
let abortHandler: (() => void) | null = null;
const cleanup = () => {
if (recheckTimer) clearInterval(recheckTimer);
if (abortHandler && signal) signal.removeEventListener('abort', abortHandler);
const idx = slotWaiters.indexOf(onSlot);
if (idx >= 0) slotWaiters.splice(idx, 1);View on GitHub (pinned to d768ba3643)
Solutions
- Wait for running processes to exit or kill stale ones so the registry count drops below TOTAL_PROCESS_HARD_CAP, then retry.
- Investigate process leaks: pruneDeadEntries() already ran, so surviving entries are live processes — find what is spawning them and add limits.
When it happens
Trigger: Fires when the process registry already holds TOTAL_PROCESS_HARD_CAP live entries and another spawn is requested, typically from a runaway hook loop, repeated failing session spawns, or leaked processes that were never reaped. The hard cap at src/supervisor/process-registry.ts:549 stops resource exhaustion before the host is overwhelmed.
Common situations: See trigger scenarios.
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/4e055a87a742d560.
Report an issue: GitHub.