ruvnet/ruflo · critical · MCPServerError
INTERNAL_ERROR
INTERNAL_ERROR
Error message
Failed to start server
What it means
This is the catch-all at the end of MCPServer.start(): any failure raised while bringing up the transport or server internals is re-thrown as MCPServerError('Failed to start server') with code ErrorCodes.INTERNAL_ERROR (-32603), and the original error is attached in the error data (third constructor argument { error }). The wrapper message is generic on purpose - the actionable cause is the attached original error and the preceding 'Failed to start MCP server' log line.
Source
Thrown at v3/@claude-flow/shared/src/mcp/server.ts:212
// Register built-in tools
await this.registerBuiltInTools();
this.running = true;
this.startupDuration = performance.now() - startTime;
this.logger.info('MCP server started', {
startupTime: `${this.startupDuration.toFixed(2)}ms`,
tools: this.toolRegistry.getToolCount(),
});
this.emit('server:started', {
startupTime: this.startupDuration,
tools: this.toolRegistry.getToolCount(),
});
} catch (error) {
this.logger.error('Failed to start MCP server', { error });
throw new MCPServerError('Failed to start server', ErrorCodes.INTERNAL_ERROR, { error });
}
}
/**
* Stop the MCP server
*/
async stop(): Promise<void> {
if (!this.running) {
return;
}
this.logger.info('Stopping MCP server');
try {
// Stop transport
if (this.transport) {
await this.transport.stop();
this.transport = undefined;View on GitHub (pinned to fa13ee4ad6)
Solutions
- Read the attached cause first: catch the error and inspect (err as MCPServerError).data.error, or the 'Failed to start MCP server' log entry - fix the underlying error, not this wrapper
- Port conflict: find and stop the holder (lsof -i :PORT) or change the configured port
- Validate transport config before start(): host/port present for http/ws, usable streams for stdio
- In non-TTY environments, switch away from stdio transport or provide explicit inputStream/outputStream in config
Example fix
// before
await server.start(); // opaque 'Failed to start server' INTERNAL_ERROR
// after
import { MCPServerError } from './mcp/types';
try {
await server.start();
} catch (e) {
const cause = (e instanceof MCPServerError ? (e.data as any)?.error : undefined) ?? e;
if ((cause as NodeJS.ErrnoException)?.code === 'EADDRINUSE') {
console.error('Port already in use - stop the old process or change the port');
}
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight common causes before start()
import { checkPortInUse } from './net';
if (config.transport === 'http' || config.transport === 'websocket') {
if (await checkPortInUse(config.port)) {
throw new Error(`Port ${config.port} already in use - choose another or stop the holder`);
}
}
await server.start(); Try / catch
try {
await server.start();
} catch (e) {
const mcpErr = e as MCPServerError;
const cause = (mcpErr?.data as { error?: unknown } | undefined)?.error ?? e;
logger.error('MCP server failed to start', { cause }); // surface the REAL cause
process.exitCode = 1; // fail fast: do not run half-started
} Prevention
- Always log the attached cause (e.data.error), never only the wrapper message
- Pre-flight port availability for network transports before start
- Run one server per port per host; containerize to avoid collisions
- Exit on startup failure rather than continuing with a broken server
When it happens
Trigger: HTTP/WebSocket transport binding an already-used port (EADDRINUSE); stdio transport with closed or unavailable stdin/stdout (containers, daemons); transport config malformed so createTransport throws inside start(); tool registry or event-handler setup throwing during startup.
Common situations: Two processes configured on the same port because an old dev-server instance still holds it; running stdio transport where stdin is not available; a version upgrade adding required config fields; insufficient permissions to bind a privileged port.
Related errors
- No models available to select task model
- Failed to execute MCP tool '${toolName}': ${error instanceof
- MCP Server already running (PID: ${status.pid})
- Failed to register MCP tools: ${registration.failed.join(',
- Server failed to start within timeout
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/2eefa87dc93d9646.
Report an issue: GitHub.