thedotmack/claude-mem · error · Error
waitForSlot aborted before queuing
Error message
waitForSlot aborted before queuing
What it means
waitForSlot accepts an optional AbortSignal and checks it before joining the waiting queue. If the signal is already aborted when the caller would otherwise have to wait (pool full), the call throws immediately rather than queueing a promise that would be rejected anyway. Fast-fails work that was cancelled before it even started waiting.
Solutions
- Check signal.aborted before attempting the spawn and skip cancelled work
- Create a fresh AbortController per spawn attempt instead of reusing one
- Order operations so the abort signal is only created when the work is actually starting
Example fix
// before
await waitForSlot(max, reusedSignal); // reusedSignal already aborted
// after
const controller = new AbortController();
if (!controller.signal.aborted) {
await waitForSlot(max, controller.signal);
} Defensive patterns
Strategy: try-catch
Validate before calling
if (signal?.aborted) return; // skip cancelled work before requesting a slot
Type guard
function isAborted(signal?: AbortSignal): boolean { return signal?.aborted === true; } Try / catch
try { const slot = await waitForSlot(max, signal); }
catch (e) { if (e.message === 'waitForSlot aborted before queuing') return; /* cancelled, not an error */ throw e; } Prevention
- Create a fresh AbortController per spawn attempt
- Check signal.aborted at the start of the async workflow
- Distinguish cancellation from failure in error handling
When it happens
Trigger: Calling waitForSlot with an AbortSignal that is already aborted while the pool is full (activeCount >= max), so the pre-queue abort check fires.
Common situations: Request cancellation (HTTP client disconnect) completed before slot acquisition; timeouts that abort the signal earlier in the pipeline; reusing an aborted controller for a second spawn attempt.
Related errors
- Chroma mutation queue is full
- failed during
- Hard cap exceeded: processes in registry (cap= ). Refusing…
- [install] Worker shutdown failed
AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17).
Data as JSON: /api/errors/5517dc743a79f858.
Report an issue: GitHub.
Appendix: source
Thrown at src/supervisor/process-registry.ts:577
* mid-response.
*/
export async function waitForSlot(
maxConcurrent: number | (() => number),
signal?: AbortSignal,
sessionId?: number | string
): Promise<SlotReservation> {
const getMax = typeof maxConcurrent === 'function' ? maxConcurrent : () => maxConcurrent;
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 < getMax()) return takeSlotReservation();
if (signal?.aborted) {
throw new Error('waitForSlot aborted before queuing');
}
logger.info('PROCESS', `Pool limit reached (${activeCount}/${getMax()}), waiting for slot...`);
return new Promise<SlotReservation>((resolve, reject) => {
let recheckTimer: ReturnType<typeof setInterval> | null = null;
let abortHandler: (() => void) | null = null;
const record: SlotWaiterRecord = {
sessionId,
parkedSince: Date.now(),
warnedParked: false,
notify: () => {},
};
const cleanup = () => {
if (recheckTimer) clearInterval(recheckTimer);
if (abortHandler && signal) signal.removeEventListener('abort', abortHandler);
const idx = slotWaiters.indexOf(record);
if (idx >= 0) slotWaiters.splice(idx, 1);View on GitHub (pinned to d8bc9755e7)