{"record":{"id":"346b2c658c1a74fb","repo":"ruvnet/ruflo","slug":"transport-name-already-exists","errorCode":null,"errorMessage":"Transport \"${name}\" already exists","messagePattern":"Transport \"(.+?)\" already exists","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/mcp/src/transport/index.ts","lineNumber":112,"sourceCode":"        connections: 1,\n      },\n    };\n  }\n}\n\nexport function createInProcessTransport(logger: ILogger): ITransport {\n  return new InProcessTransport(logger);\n}\n\nexport class TransportManager {\n  private transports: Map<string, ITransport> = new Map();\n  private running = false;\n\n  constructor(private readonly logger: ILogger) {}\n\n  addTransport(name: string, transport: ITransport): void {\n    if (this.transports.has(name)) {\n      throw new Error(`Transport \"${name}\" already exists`);\n    }\n    this.transports.set(name, transport);\n    this.logger.debug('Transport added', { name, type: transport.type });\n  }\n\n  async removeTransport(name: string): Promise<boolean> {\n    const transport = this.transports.get(name);\n    if (!transport) {\n      return false;\n    }\n\n    await transport.stop();\n    this.transports.delete(name);\n    this.logger.debug('Transport removed', { name });\n    return true;\n  }\n\n  getTransport(name: string): ITransport | undefined {","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/mcp/src/transport/index.ts#L94-L130","documentation":"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.","triggerScenarios":"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'.","commonSituations":"Framework boilerplate and user code both registering a transport; retrying an initialization sequence that already succeeded; name generation from env/counters repeating across modules.","solutions":["Check manager.getTransport(name) (or getTransportNames()) first and skip if present","Await manager.removeTransport(name) first when deliberately replacing a transport","Derive names from the transport type or a unique id per registration site"],"exampleFix":"// before\nmanager.addTransport('http', httpTransport);\n\n// after\nif (!manager.getTransport('http')) {\n  manager.addTransport('http', httpTransport);\n} else {\n  await manager.removeTransport('http');\n  manager.addTransport('http', httpTransport);\n}","handlingStrategy":"validation","validationCode":"if (manager.getTransport(name)) {\n  await manager.removeTransport(name); // deliberate replacement\n}\nmanager.addTransport(name, transport);","typeGuard":null,"tryCatchPattern":"try {\n  manager.addTransport(name, transport);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('already exists')) {\n    // double init - skip or replace via removeTransport first\n  } else {\n    throw e;\n  }\n}","preventionTips":["Check getTransport(name) before addTransport","Use unique names per registration site (e.g. `${subsystem}:${type}`)","Make init routines idempotent so re-running them cannot double-register"],"tags":["transport","registration","duplicate-key","lifecycle"],"backgroundTag":"duplicate-registration","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}