ruvnet/ruflo · warning · Error

Max sessions (${this.config.maxSessions}) reached

Error message

Max sessions (${this.config.maxSessions}) reached

What it means

Thrown by BrowserSwarm.spawnAgent when the number of live BrowserService entries (services.size) has already reached config.maxSessions. The swarm enforces a hard cap to bound browser process/memory cost; each spawn allocates one BrowserService with its own sessionId and they are stored in the services Map for the swarm's lifetime.

Source

Thrown at v3/@claude-flow/browser/src/application/browser-service.ts:488

// ============================================================================
// Browser Swarm Coordinator
// ============================================================================

export class BrowserSwarmCoordinator {
  private config: BrowserSwarmConfig;
  private services: Map<string, BrowserService> = new Map();
  private sharedData: Map<string, unknown> = new Map();

  constructor(config: BrowserSwarmConfig) {
    this.config = config;
  }

  /**
   * Spawn a new browser agent in the swarm
   */
  async spawnAgent(role: 'navigator' | 'scraper' | 'validator' | 'tester' | 'monitor'): Promise<BrowserService> {
    if (this.services.size >= this.config.maxSessions) {
      throw new Error(`Max sessions (${this.config.maxSessions}) reached`);
    }

    const sessionId = `${this.config.sessionPrefix}-${role}-${Date.now()}`;
    const service = new BrowserService({
      sessionId,
      role,
      capabilities: this.getCapabilitiesForRole(role),
      defaultTimeout: 30000,
      headless: true,
    });

    this.services.set(sessionId, service);
    return service;
  }

  /**
   * Get capabilities for a role
   */

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. Close/recycle sessions when a role finishes (service.stop()/browser.close() and services.delete(sessionId)) so the slot is freed.
  2. Raise config.maxSessions to match the workload, but only after confirming host RAM/CPU headroom for that many headless browsers.
  3. Queue additional spawn requests and drain them as slots free up instead of failing fast.
  4. Periodically reap dead entries from services (a crashed browser still holds a Map slot until deleted).

Example fix

// before
const svc = await swarm.spawnAgent("scraper"); // throws at cap
// after
if (swarm.services.size >= swarm.config.maxSessions) {
  await recycleOldestIdleSession(swarm);
}
const svc = await swarm.spawnAgent("scraper");
Defensive patterns

Strategy: validation

Validate before calling

function hasCapacity(swarm: BrowserSwarm): boolean {
  return swarm.services.size < swarm.config.maxSessions;
}
if (!hasCapacity(swarm)) {
  await recycleOldestIdleSession(swarm); // or queue the request
}
await swarm.spawnAgent("scraper");

Type guard

function isBrowserSwarm(x: unknown): x is { services: Map<string, unknown>; config: { maxSessions: number } } {
  return !!x && x instanceof Map.constructor === false &&
    (x as { services?: Map<string, unknown> }).services instanceof Map &&
    typeof (x as { config?: { maxSessions?: number } }).config?.maxSessions === "number";
}

Try / catch

try {
  return await swarm.spawnAgent(role);
} catch (e) {
  if (String((e as Error)?.message).startsWith("Max sessions")) {
    await waitForFreeSlot(swarm, timeoutMs);
    return await swarm.spawnAgent(role);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling swarm.spawnAgent(role) more than maxSessions times without closing any prior session; roles are navigator|scraper|validator|tester|monitor and each consumes one slot regardless of role.

Common situations: A crawl/exploration loop that spawns per-page agents and never tears them down; a long-running job whose maxSessions was sized for short tasks; headless browsers leaking (crashed but not removed from the Map).

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/96b58c21dfb7d7ec. Report an issue: GitHub.