ruvnet/ruflo · error · Error

TransportManager already running

Error message

TransportManager already running

What it means

TransportManager.startAll() starts every registered transport and refuses to run twice via its running flag (a public isRunning() accessor exists). A second startAll() - including one issued while the first is still awaiting a slow transport - throws. Note per-transport failures also propagate: if any transport.start() rejects, startAll() logs 'Failed to start transport' and rejects, so retry logic must stopAll() before retrying.

Source

Thrown at v3/@claude-flow/shared/src/mcp/transport/index.ts:186

   * Get a transport by name
   */
  getTransport(name: string): ITransport | undefined {
    return this.transports.get(name);
  }

  /**
   * Get all transport names
   */
  getTransportNames(): string[] {
    return Array.from(this.transports.keys());
  }

  /**
   * Start all transports
   */
  async startAll(): Promise<void> {
    if (this.running) {
      throw new Error('TransportManager already running');
    }

    this.logger.info('Starting all transports', { count: this.transports.size });

    const startPromises = Array.from(this.transports.entries()).map(
      async ([name, transport]) => {
        try {
          await transport.start();
          this.logger.info('Transport started', { name, type: transport.type });
        } catch (error) {
          this.logger.error('Failed to start transport', { name, error });
          throw error;
        }
      }
    );

    await Promise.all(startPromises);
    this.running = true;

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Memoize: ready ??= manager.startAll() so concurrent and duplicate calls coalesce
  2. On a failed startAll(), await manager.stopAll() before retrying so state resets cleanly
  3. In restart flows always pair stopAll() then startAll()

Example fix

// before
await manager.startAll();
// ...
await manager.startAll(); // throws: already running

// after
if (!manager.isRunning()) {
  await manager.startAll();
}
// or memoize:
const ready = startPromise ??= manager.startAll();
Defensive patterns

Strategy: validation

Validate before calling

if (manager.isRunning()) {
  return; // already up
}
await manager.startAll();

Try / catch

try {
  await manager.startAll();
} catch (e) {
  if (e instanceof Error && /already running/.test(e.message)) return;
  // a real transport failure: reset state before any retry
  await manager.stopAll().catch(() => {});
  throw e;
}

Prevention

When it happens

Trigger: Calling startAll() from two init modules; re-invoking after a first attempt where one transport failed but the manager flag was already set; restart logic that skips stopAll(); racing a health-check that also triggers startup.

Common situations: Two subsystems both 'ensuring' the manager is up; retry/backoff around startup; tests reusing a manager across cases without stopping it.

Related errors


AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18). Data as JSON: /api/errors/0283c9c40e06f978. Report an issue: GitHub.