ruvnet/ruflo · error · Error

Transport "${name}" already exists

Error message

Transport "${name}" already exists

What it means

TransportManager keeps transports in a Map keyed by a caller-chosen unique name. addTransport(name, transport) throws when the name is already present rather than silently replacing a possibly-running transport. Presence can be checked read-only via getTransportNames()/getTransport(name), and entries are removed with removeTransport(name).

Source

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

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

/**
 * Transport manager for multi-transport scenarios
 */
export class TransportManager {
  private transports: Map<string, ITransport> = new Map();
  private running = false;

  constructor(private readonly logger: ILogger) {}

  /**
   * Add a transport
   */
  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 });
  }

  /**
   * Remove a transport
   */
  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;

View on GitHub (pinned to fa13ee4ad6)

Solutions

  1. Check membership first: if (!manager.getTransportNames().includes(name)) manager.addTransport(name, t)
  2. Name transports by role + instance (http-main, http-metrics) so distinct transports cannot collide
  3. For re-registration flows, await manager.removeTransport(name) first, then add the new instance

Example fix

// before
manager.addTransport('http', httpA);
manager.addTransport('http', httpB); // throws: already exists

// after
manager.addTransport('http-main', httpA);
manager.addTransport('http-metrics', httpB);
Defensive patterns

Strategy: validation

Validate before calling

if (manager.getTransportNames().includes(name)) {
  throw new Error(`transport '${name}' already registered - pick a unique name`);
}
manager.addTransport(name, transport);

Try / catch

try {
  manager.addTransport(name, transport);
} catch (e) {
  if (e instanceof Error && e.message.includes('already exists')) {
    return; // idempotent registration for restart flows
  }
  throw e;
}

Prevention

When it happens

Trigger: Two setup functions both registering a transport named 'http'; re-running a registration routine after a partial failure where the first add already succeeded; names generated only from the transport type (not per-instance) so a second listener of the same type collides.

Common situations: Plugin/module systems where several modules register transports into one manager; init retries; config reload re-running wiring; name derived from a value that does not change between re-registrations.

Related errors


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