perwendel/spark · error · IllegalStateException

WebSockets are only supported in the embedded server

Error message

WebSockets are only supported in the embedded server

What it means

WebSocket handlers in Spark are registered via webSocket(path, wrapper), which delegates to addWebSocketHandler. WebSockets require Spark's own embedded Jetty server; when Spark is running as a servlet inside an external container (isRunningFromServlet() is true) it cannot install its WebSocket support, so registration throws IllegalStateException.

Solutions

  1. Run the app with the embedded Spark server (main() with Spark.port/threadPool etc.) instead of deploying as a WAR.
  2. Handle WebSockets with the servlet container's own native WebSocket support (javax.websocket endpoints) when servlet deployment is mandatory.
  3. Remove or conditionally guard webSocket() registration when running in servlet mode.

Example fix

// before
public class App extends SparkApplication { // deployed as WAR
    public void init() { webSocket("/ws", WsHandler.class); } // throws
}
// after
// deploy with embedded server: run App.main() directly, or use container-native JSR-356 endpoints for /ws
Defensive patterns

Strategy: validation

Validate before calling

if (!isEmbeddedMode()) { // e.g. you deploy as WAR
    throw new IllegalStateException("Register WebSockets only in embedded mode");
}
Spark.webSocket("/ws", WsHandler.class);

Try / catch

try {
    Spark.webSocket("/ws", WsHandler.class);
} catch (IllegalStateException e) {
    LOG.warn("WebSockets unavailable in servlet mode; using container-native endpoints");
}

Prevention

When it happens

Trigger: Calling webSocket("/ws", handler) (or webSocketAnnotation) while the app is deployed as a WAR in an external servlet container such as Tomcat/WildFly, i.e. running with the spark-servlet bootstrap instead of the embedded server.

Common situations: Deploying a Spark app as a WAR to a corporate Tomcat instance and adding WebSocket endpoints; switching from embedded jetty (dev) to servlet deployment (prod) without removing WebSocket routes.

Related errors


AI-assisted analysis of perwendel/spark@1973e402f5 (2026-09-10). Data as JSON: /api/errors/7f8f72522f4fa0e7. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/spark/Service.java:427

    /**
     * Maps the given path to the given WebSocket handler instance.
     * <p>
     * This is currently only available in the embedded server mode.
     *
     * @param path    the WebSocket path.
     * @param handler the handler instance that will manage the WebSocket connection to the given path.
     */
    public void webSocket(String path, Object handler) {
        addWebSocketHandler(path, new WebSocketHandlerInstanceWrapper(handler));
    }

    private synchronized void addWebSocketHandler(String path, WebSocketHandlerWrapper handlerWrapper) {
        if (initialized) {
            throwBeforeRouteMappingException();
        }
        if (isRunningFromServlet()) {
            throw new IllegalStateException("WebSockets are only supported in the embedded server");
        }
        requireNonNull(path, "WebSocket path cannot be null");
        if (webSocketHandlers == null) {
            webSocketHandlers = new HashMap<>();
        }

        webSocketHandlers.put(path, handlerWrapper);
    }

    /**
     * Sets the max idle timeout in milliseconds for WebSocket connections.
     *
     * @param timeoutMillis The max idle timeout in milliseconds.
     * @return the object with max idle timeout set for WebSocket connections
     */
    public synchronized Service webSocketIdleTimeoutMillis(long timeoutMillis) {
        if (initialized) {
            throwBeforeRouteMappingException();

View on GitHub (pinned to 1973e402f5)