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

  1. Wait for running processes to exit or kill stale ones so the registry count drops below TOTAL_PROCESS_HARD_CAP, then retry.
  2. 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.