ruvnet/ruflo · error
HTTP transport already running
Error message
HTTP transport already running
What it means
HTTPTransport.start() binds an express app via createServer plus a WebSocketServer and is guarded by an internal running flag. A second start() on the same instance throws immediately: the port is already bound by the first start and the middleware/routes/sockets are already installed. stop() closes the server and resets the flag, enabling a stop-then-start restart.
Source
Thrown at v3/@claude-flow/shared/src/mcp/transport/http.ts:86
private httpRequests = 0;
private wsMessages = 0;
constructor(
private readonly logger: ILogger,
private readonly config: HttpTransportConfig
) {
super();
this.app = express();
this.setupMiddleware();
this.setupRoutes();
}
/**
* Start the transport
*/
async start(): Promise<void> {
if (this.running) {
throw new Error('HTTP transport already running');
}
this.logger.info('Starting HTTP transport', {
host: this.config.host,
port: this.config.port,
});
// Create HTTP server
this.server = createServer(this.app);
// Create WebSocket server
this.wss = new WebSocketServer({
server: this.server,
path: '/ws',
});
this.setupWebSocketHandlers();
View on GitHub (pinned to fa13ee4ad6)
Solutions
- Memoize the start call: startPromise ??= transport.start()
- For restart flows: await transport.stop() before start() again
- Alternatively build a fresh HTTPTransport instance for the new lifecycle instead of restarting the old one
Example fix
// before await transport.start(); await reloadConfig(); await transport.start(); // throws: already running // after await transport.start(); await reloadConfig(); await transport.stop(); await transport.start();
Defensive patterns
Strategy: validation
Validate before calling
let running = false;
async function startOnce() {
if (running) return;
await transport.start();
running = true;
}
await startOnce(); Try / catch
try {
await transport.start();
} catch (e) {
if (e instanceof Error && /already running/.test(e.message)) return; // idempotent
throw e;
} Prevention
- Memoize the transport start promise
- Always stop() before restart; or build a new HTTPTransport for the new lifecycle
- Keep transport instances module-scoped with a single owner
When it happens
Trigger: Calling transport.start() twice; restart-on-config-reload code that re-runs setup without stop(); an orchestrator handing the same transport instance to two modules that each start it; retry wrapper around start().
Common situations: Config hot-reload rebuilding wiring but reusing the transport object; health-check harness that starts the transport on every probe; module-level transport shared across tests.
Related errors
- TransportManager already running
- Stdio transport already running
- WebSocket transport already running
- HTTP transport already running
- Stdio transport already running
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/c817457ae27ff5e8.
Report an issue: GitHub.