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
- Check membership first: if (!manager.getTransportNames().includes(name)) manager.addTransport(name, t)
- Name transports by role + instance (http-main, http-metrics) so distinct transports cannot collide
- 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
- Derive transport names from role + instance, not a constant
- Presence-check with getTransportNames() before add in idempotent init code
- Treat duplicate-name throws as a wiring bug to fix, not to silence routinely
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
- HTTP transport failed: ${firstError instanceof Error ? first
- Transport "${name}" already exists
- Stdio transport already running
- HTTP transport already running
- HTTP transport requires host and port configuration
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/34c88cc26872fb88.
Report an issue: GitHub.