apache/shardingsphere · critical · IOException
Failed to start %s server.
Error message
Failed to start %s server.
What it means
MCPRuntimeLauncher.launch() builds the runtime context, chooses a StreamableHttpMCPServer or StdioMCPServer from the transport type, and calls start(); if start() throws IOException, the launcher stops the partially started server and rethrows IOException('Failed to start %s server.'), naming HTTP or STDIO. The message is a wrapper — the attached cause carries the actual transport failure.
Source
Thrown at mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/MCPRuntimeLauncher.java:64
/**
* Launch.
*
* @param config launch configuration
* @return MCP Server
* @throws IOException when the active server startup fails
*/
public MCPRuntimeServer launch(final MCPLaunchConfiguration config) throws IOException {
ShardingSpherePreconditions.checkNotNull(config, () -> new IllegalArgumentException("MCP launch configuration cannot be null."));
MCPRuntimeContext runtimeContext = new MCPRuntimeContext(new MCPSessionManager(config.getDatabases()), new MCPDatabaseCapabilityProvider(config.getDatabases()),
config.getTransportType());
MCPRuntimeServer result = isHttpTransport(config) ? new StreamableHttpMCPServer(config.getHttpTransport(), runtimeContext) : new StdioMCPServer(runtimeContext);
try {
result.start();
log.info(createStartupLogMessage(config, result));
} catch (final IOException ex) {
result.stop();
throw new IOException(String.format("Failed to start %s server.", isHttpTransport(config) ? "HTTP" : "STDIO"), ex);
}
return result;
}
private String createStartupLogMessage(final MCPLaunchConfiguration config, final MCPRuntimeServer server) {
return isHttpTransport(config) ? createHttpStartupLogMessage(config, (StreamableHttpMCPServer) server) : createStdioStartupLogMessage(config);
}
private String createHttpStartupLogMessage(final MCPLaunchConfiguration config, final StreamableHttpMCPServer server) {
String endpoint = String.format("http://%s:%d%s", config.getHttpTransport().getBindHost(), server.getLocalPort(), config.getHttpTransport().getEndpointPath());
SessionAttributionResolver sessionAttributionResolver = new SessionAttributionResolver(config.getHttpTransport().getSessionAttributionSource());
return String.format("ShardingSphere MCP Server started, transport=%s, config=%s, databases=%d, endpoint=%s, session_attribution=%s, logs=%s.",
config.getTransportType().name().toLowerCase(Locale.ENGLISH), configPath, config.getDatabases().size(), endpoint, sessionAttributionResolver.getSummary(), LOG_PATH);
}
private String createStdioStartupLogMessage(final MCPLaunchConfiguration config) {
return String.format("ShardingSphere MCP Server started, transport=%s, config=%s, databases=%d, logs=%s. Stdout is reserved for MCP protocol frames.",
config.getTransportType().name().toLowerCase(Locale.ENGLISH), configPath, config.getDatabases().size(), LOG_PATH);View on GitHub (pinned to e952770a21)
Solutions
- Read the cause of the IOException (getCause) — it distinguishes port-in-use, bind failure, or stream problems.
- Free the configured HTTP port or change it to an unused one, and set bindHost to a local interface (127.0.0.1 unless LAN exposure is intended).
- For STDIO transport, run the launcher attached to real stdin/stdout (no daemonization) and keep logs on stderr only.
- Ensure one MCP instance per endpoint; stop previous instances before relaunching.
- Verify write access to the temp directory the embedded server uses.
Example fix
# before java -jar shardingsphere-mcp.jar --transport http --port 8080 # port already bound # after # free the port or pick another java -jar shardingsphere-mcp.jar --transport http --bind-host 127.0.0.1 --port 18080
Defensive patterns
Strategy: try-catch
Validate before calling
// before launch, verify the HTTP port is free
try (java.net.ServerSocket probe = new java.net.ServerSocket(port, 1, InetAddress.getByName(bindHost))) { /* port free */ } Try / catch
try { MCPRuntimeServer server = launcher.launch(config); } catch (final IOException ex) { Throwable cause = ex.getCause(); /* cause distinguishes port bind vs stdio vs temp-dir failure */ } Prevention
- Pre-check port availability and bind-host validity for HTTP transport.
- Run STDIO transport attached to real stdin/stdout with logs on stderr.
- Ensure only one MCP instance per endpoint and a writable temp dir.
- Always inspect the cause, not just the wrapper message.
When it happens
Trigger: Launching the ShardingSphere MCP server with an HTTP transport whose port is taken or bind host is invalid (delegated to the Tomcat-based server, which throws IOException), or with a STDIO transport where the standard streams cannot be acquired; any IOException from server.start() triggers the wrap after result.stop().
Common situations: Port already in use for the HTTP endpoint; bindHost set to an interface the host does not own; running in a container/sandbox where STDIO is detached; conflicting MCP instance on the same endpoint path; insufficient permission to create the temp directory used by the embedded server.
Related errors
- MCP configuration file `%s` does not exist.
- Failed to start embedded Tomcat runtime.
- System property `%s` must be a positive integer, but was `%s
- Missing required format info in createBatch()
- Failed to read java.sql.Blob content
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/f4932b487df70265.
Report an issue: GitHub.