ruvnet/ruflo · error · Error
Bulkhead '${this.options.name}' is full. Max concurrent: ${t
Error message
Bulkhead '${this.options.name}' is full. Max concurrent: ${this.options.maxConcurrent}, queue: ${this.options.maxQueue} What it means
Bulkhead is a resilience4j-style concurrency limiter. execute() runs fn immediately while active < maxConcurrent, otherwise enqueues while the queue holds fewer than maxQueue entries. When both execution slots and queue slots are exhausted it increments the rejected counter, fires options.onRejected('full'), and throws — deliberate fail-fast overload protection rather than unbounded queuing.
Source
Thrown at v3/@claude-flow/shared/src/resilience/bulkhead.ts:110
constructor(options: BulkheadOptions) {
super();
this.options = { ...DEFAULT_OPTIONS, ...options };
}
/**
* Execute a function within the bulkhead
*/
async execute<T>(fn: () => Promise<T>): Promise<T> {
// If there's room for execution, run immediately
if (this.active < this.options.maxConcurrent) {
return this.runNow(fn);
}
// Check if queue is full
if (this.queue.length >= this.options.maxQueue) {
this.rejected++;
this.options.onRejected?.('full');
throw new Error(`Bulkhead '${this.options.name}' is full. Max concurrent: ${this.options.maxConcurrent}, queue: ${this.options.maxQueue}`);
}
// Add to queue
return this.addToQueue(fn);
}
/**
* Get current statistics
*/
getStats(): BulkheadStats {
return {
active: this.active,
queued: this.queue.length,
maxConcurrent: this.options.maxConcurrent,
maxQueue: this.options.maxQueue,
completed: this.completed,
rejected: this.rejected,
timedOut: this.timedOut,View on GitHub (pinned to fa13ee4ad6)
Solutions
- Raise maxConcurrent and/or maxQueue in the Bulkhead options to cover peak concurrency.
- Register options.onRejected to shed load gracefully (log, 429, drop, backpressure) instead of relying on the throw.
- Check getStats() before submitting and defer when active and queue are near their maxima.
- Attach timeouts/retries to the wrapped fn so execution slots are released promptly even when downstream hangs.
Example fix
// before
const bulkhead = new Bulkhead({ name: 'api', maxConcurrent: 5, maxQueue: 10 });
const r = await bulkhead.execute(() => callApi()); // throws at 5 active + 10 queued
// after
const bulkhead = new Bulkhead({
name: 'api',
maxConcurrent: 20,
maxQueue: 100,
onRejected: (reason) => metrics.increment('bulkhead.rejected', { reason }),
}); Defensive patterns
Strategy: fallback
Validate before calling
const s = bulkhead.getStats();
// active and queue occupancy vs your configured maxima
if (s.active >= opts.maxConcurrent && s.queue >= opts.maxQueue) {
// at capacity: defer, shed load, or throttle before calling execute
} Try / catch
try {
result = await bulkhead.execute(fn);
} catch (e) {
if (e instanceof Error && e.message.includes('is full. Max concurrent:')) {
result = await degradeOrEnqueueElsewhere(); // serve a fallback instead of crashing
} else {
throw e;
}
} Prevention
- Size maxConcurrent and maxQueue from measured peak load plus headroom, not averages.
- Always configure onRejected so rejections are observable before they become exceptions.
- Attach timeouts to the wrapped fn so execution slots free even when downstream hangs.
- Bound caller concurrency upstream (queues, worker pools) so submissions never exceed bulkhead capacity.
When it happens
Trigger: Issuing more than maxConcurrent + maxQueue concurrent execute() calls; slow wrapped functions (downstream HTTP/DB calls) holding all execution slots while new submissions keep arriving; a burst of fan-out work (e.g. Promise.all over a large array) funneled through one small bulkhead.
Common situations: maxConcurrent/maxQueue sized for average rather than peak load; a degraded downstream dependency so slots never free; load tests or traffic spikes revealing the cap; missing onRejected handler so rejections only surface as exceptions.
Related errors
- Agent ${this.id} has reached max concurrent tasks
- Worker ${this.id} at capacity (${maxTasks} tasks)
- Issue ${input.issueId} is already claimed by ${issue.claimed
- swarm state is busy; retry the outcome update
- Circuit breaker is open. Service temporarily unavailable.
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/616c52fee153bbcf.
Report an issue: GitHub.