ruvnet/ruflo · error · Error

Transport "${name}" already exists

Error message

Transport "${name}" already exists

What it means

TransportManager stores transports in a Map keyed by a caller-chosen name; addTransport(name, transport) throws if the name is already registered, preventing silent replacement of a live transport. Names are arbitrary strings with no built-in namespacing, so collisions are purely a caller-side naming problem.

Source

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

        connections: 1,
      },
    };
  }
}

export function createInProcessTransport(logger: ILogger): ITransport {
  return new InProcessTransport(logger);
}

export class TransportManager {
  private transports: Map<string, ITransport> = new Map();
  private running = false;

  constructor(private readonly logger: ILogger) {}

  addTransport(name: string, transport: ITransport): void {
    if (this.transports.has(name)) {
      throw new Error(`Transport "${name}" already exists`);
    }
    this.transports.set(name, transport);
    this.logger.debug('Transport added', { name, type: transport.type });
  }

  async removeTransport(name: string): Promise<boolean> {
    const transport = this.transports.get(name);
    if (!transport) {
      return false;
    }

    await transport.stop();
    this.transports.delete(name);
    this.logger.debug('Transport removed', { name });
    return true;
  }

  getTransport(name: string): ITransport | undefined {

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Check manager.getTransport(name) (or getTransportNames()) first and skip if present
  2. Await manager.removeTransport(name) first when deliberately replacing a transport
  3. Derive names from the transport type or a unique id per registration site

Example fix

// before
manager.addTransport('http', httpTransport);

// after
if (!manager.getTransport('http')) {
  manager.addTransport('http', httpTransport);
} else {
  await manager.removeTransport('http');
  manager.addTransport('http', httpTransport);
}
Defensive patterns

Strategy: validation

Validate before calling

if (manager.getTransport(name)) {
  await manager.removeTransport(name); // deliberate replacement
}
manager.addTransport(name, transport);

Try / catch

try {
  manager.addTransport(name, transport);
} catch (e) {
  if (e instanceof Error && e.message.includes('already exists')) {
    // double init - skip or replace via removeTransport first
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Registering 'http' twice (a default registration plus a custom one); an init routine that re-runs on hot reload without constructing a new TransportManager; two subsystems both registering under a generic name like 'main' or 'default'.

Common situations: Framework boilerplate and user code both registering a transport; retrying an initialization sequence that already succeeded; name generation from env/counters repeating across modules.

Related errors


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