apache/shardingsphere · critical · IOException
Failed to start embedded Tomcat runtime.
Error message
Failed to start embedded Tomcat runtime.
What it means
StreamableHttpMCPServer.start() assembles an embedded Tomcat (connector on the configured port/bind host, temp base dir, transport servlet mapped at the endpoint path) and calls tomcat.start(). A Tomcat LifecycleException — most commonly a bind failure — is caught, stop() is invoked to release partial state, and the error is rethrown as IOException('Failed to start embedded Tomcat runtime.').
Source
Thrown at mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServer.java:88
}
}
private void startEmbeddedTomcat() throws IOException {
try {
tomcat = new Tomcat();
connector = new Connector();
connector.setPort(config.getPort());
connector.setProperty("address", config.getBindHost());
tomcat.setConnector(connector);
baseDirectory = Files.createTempDirectory("shardingsphere-mcp-tomcat");
tomcat.setBaseDir(baseDirectory.toString());
Context context = tomcat.addContext("", baseDirectory.toString());
((StandardContext) context).setClearReferencesRmiTargets(false);
registerTransportServlet(context);
tomcat.start();
} catch (final LifecycleException ex) {
stop();
throw new IOException("Failed to start embedded Tomcat runtime.", ex);
}
}
private void registerTransportServlet(final Context context) {
Wrapper servletWrapper = Tomcat.addServlet(context, "mcp-streamable-http", transportServlet);
servletWrapper.setAsyncSupported(true);
context.addServletMappingDecoded(config.getEndpointPath(), "mcp-streamable-http");
}
@Override
public void stop() {
closeTomcat();
closeSyncServer();
connector = null;
deleteBaseDirectory();
}
private void closeTomcat() {View on GitHub (pinned to e952770a21)
Solutions
- Check the IOException's cause — LifecycleException text names bind vs. lifecycle failure.
- Free the port (ss -ltnp / lsof -i :<port>) or configure an unused one.
- Set bindHost to an address that exists on the machine (127.0.0.1 for local-only use).
- Ensure the temp directory is writable and not exhausted; set a writable java.io.tmpdir if needed.
- Run only one HTTP MCP server per port/endpoint path.
Example fix
# before # port 8080 already in use -> IOException "Failed to start embedded Tomcat runtime." # after ss -ltnp | grep 8080 # find and stop the conflicting process, or: java -jar mcp.jar --transport http --bind-host 127.0.0.1 --port 18080
Defensive patterns
Strategy: validation
Validate before calling
// before start: confirm the endpoint address is bindable
try (java.net.ServerSocket probe = new java.net.ServerSocket(port, 1, InetAddress.getByName(bindHost))) { /* bind will succeed */ } catch (final java.net.BindException ex) { throw new IllegalStateException("Port/host unavailable: " + bindHost + ":" + port, ex); } Try / catch
try { server.start(); } catch (final IOException ex) { Throwable cause = ex.getCause(); /* LifecycleException cause: free the port, fix bindHost, ensure temp dir writable */ } Prevention
- Reserve and pre-check the HTTP port before startup.
- Bind to an interface that exists (127.0.0.1 for local-only).
- Keep the temp directory writable and not full.
- Run one MCP HTTP server per port/endpoint and stop stale instances first.
When it happens
Trigger: Launching the MCP HTTP transport when the configured port is already bound, the bindHost address is not assigned to the host, or the temp base directory cannot be created; Tomcat then throws LifecycleException from start(), which this handler converts to IOException.
Common situations: Another MCP instance or unrelated service on the same port; bindHost set to 0.0.0.0-alikes or an interface absent in the container; read-only or full /tmp preventing Files.createTempDirectory; SELinux/AppArmor blocking the embedded Tomcat.
Related errors
- Failed to start %s server.
- MCP configuration file `%s` does not exist.
- System property `%s` must be a positive integer, but was `%s
- Invalid port `%s`.
- Missing required format info in createBatch()
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/68e92a8e05dfe08d.
Report an issue: GitHub.