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
- Memoize: ready ??= manager.startAll() so concurrent and duplicate calls coalesce
- On a failed startAll(), await manager.stopAll() before retrying so state resets cleanly
- 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
- Memoize the startAll promise so concurrent init paths coalesce
- Use the public isRunning() accessor before calling startAll()
- After a failed startAll(), stopAll() before retrying so manager state resets
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
- HTTP transport already running
- Stdio transport already running
- WebSocket transport already running
- Stdio transport already running
- Server already running
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/0283c9c40e06f978.
Report an issue: GitHub.