ruvnet/ruflo · error · Error
WebSocket transport already running
Error message
WebSocket transport already running
What it means
WebSocketTransport.start() creates an HTTP server for the WebSocket upgrade (answering 426 to non-WS requests) and binds host, port and path (default '/ws'); it is guarded by a running flag. A second start() on the same instance throws because the port/path are already bound and client bookkeeping is live. stop() releases the server and resets the flag.
Source
Thrown at v3/@claude-flow/shared/src/mcp/transport/websocket.ts:92
// Statistics
private messagesReceived = 0;
private messagesSent = 0;
private errors = 0;
private totalConnections = 0;
constructor(
private readonly logger: ILogger,
private readonly config: WebSocketTransportConfig
) {
super();
}
/**
* Start the transport
*/
async start(): Promise<void> {
if (this.running) {
throw new Error('WebSocket transport already running');
}
this.logger.info('Starting WebSocket transport', {
host: this.config.host,
port: this.config.port,
path: this.config.path || '/ws',
});
// Create HTTP server for WebSocket upgrade
this.server = createServer((req, res) => {
// Simple HTTP response for non-WebSocket requests
res.writeHead(426, { 'Content-Type': 'text/plain' });
res.end('Upgrade Required - WebSocket connection expected');
});
// Create WebSocket server
this.wss = new WebSocketServer({
server: this.server,View on GitHub (pinned to fa13ee4ad6)
Solutions
- Memoize: startPromise ??= transport.start()
- Restart properly: await transport.stop() then start()
- Otherwise create a new WebSocketTransport instance for the new lifecycle
Example fix
// before await ws.start(); await reloadConfig(); await ws.start(); // throws: already running // after await ws.start(); await reloadConfig(); await ws.stop(); await ws.start();
Defensive patterns
Strategy: validation
Validate before calling
let startPromise: Promise<void> | null = null;
function ensureWsStarted() {
return (startPromise ??= wsTransport.start());
} Try / catch
try {
await wsTransport.start();
} catch (e) {
if (e instanceof Error && /already running/.test(e.message)) return;
throw e;
} Prevention
- Memoize the WebSocket start promise; call it from one owner
- Restart via stop() then start(), never start() over a live transport
- In reconnect logic, reuse the existing connection instead of re-starting the transport
When it happens
Trigger: Calling start() twice; reconnect/reload logic reusing the transport without stop(); two modules sharing one WebSocketTransport instance both starting it; retry wrapper around start() firing after a slow first success.
Common situations: Config reload paths that rebuild wiring but keep the transport object; test harnesses sharing a module-level transport; supervisors that 'ensure started' by calling start() unconditionally.
Related errors
- HTTP transport already running
- TransportManager already running
- Stdio transport already running
- Stdio transport already running
- WebSocket transport already running
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/19c93370a3272fc0.
Report an issue: GitHub.