apache/pulsar · critical · IOException

Failed to start HTTP server on ports ${ports}

Error message

Failed to start HTTP server on ports ${ports}

What it means

WebServer.start boots the embedded Jetty server; if server.start() throws, it collects the ports of the configured connectors and wraps the failure in an IOException listing them. This tells the operator which HTTP/HTTPS ports the web console/REST endpoints failed to bind while the root cause (usually BindException) is attached as the cause.

Source

Thrown at pulsar-proxy/src/main/java/org/apache/pulsar/proxy/server/WebServer.java:381

                .findFirst().ifPresent(c -> {
                        WebServer.this.externalServicePort = ((ServerConnector) c).getPort();
                    });

            // server reports URI of first servlet, we want to strip that path off
            URI reportedURI = server.getURI();
            serviceURI = new URI(reportedURI.getScheme(),
                                 null,
                                 reportedURI.getHost(),
                                 reportedURI.getPort(),
                                 null, null, null);
        } catch (Exception e) {
            List<Integer> ports = new ArrayList<>();
            for (Connector c : server.getConnectors()) {
                if (c instanceof ServerConnector) {
                    ports.add(((ServerConnector) c).getPort());
                }
            }
            throw new IOException("Failed to start HTTP server on ports " + ports, e);
        }

        log.info()
                .attr("getServiceUri", getServiceUri())
                .log("Server started at end point");
    }

    public void stop() throws Exception {
        // PIP-478: dispose the TLS factory subscription and close the factory, if the new path was used.
        releaseTlsResources();
        server.stop();
        webServiceExecutor.stop();
        log.info("Server stopped successfully");
    }

    public boolean isStarted() {
        return server.isStarted();
    }

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect the cause (usually BindException) and free the listed ports or change the web service port in config
  2. Ensure only one instance runs on the host — stop the stale process holding the port
  3. Verify the bindAddress is valid for the machine and ports are unprivileged or you have permission
  4. If TLS connector is involved, validate the TLS/keystore configuration before restarting

Example fix

// before
webServicePort=8080  # already in use

// after
webServicePort=8081
Defensive patterns

Strategy: validation

Validate before calling

int webPort = webServer.getServicePort();
try (ServerSocket ss = new ServerSocket()) {
    ss.bind(new InetSocketAddress(webPort));
} catch (IOException e) {
    throw new IllegalStateException("Web port " + webPort + " unavailable before WebServer.start(): " + e.getMessage());
}

Type guard

boolean webPortAvailable(int port) {
    try (ServerSocket ss = new ServerSocket(port)) {
        return true;
    } catch (IOException e) {
        return false;
    }
}

Try / catch

try {
    webServer.start();
} catch (IOException e) {
    if (e.getCause() != null && e.getCause().getClass().getSimpleName().contains("BindException")) {
        LOG.error("Jetty could not bind web ports ({}): {}", e.getMessage(), e.getCause().getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling webServer.start() when the Jetty connector cannot bind: web service port already in use by another process, configured bindAddress unavailable, insufficient permission for a privileged port, or TLS configuration failure on the SSL connector.

Common situations: Broker/proxy web port 8080 already used by another service (common collision with other Java apps); stale proxy from a previous run still holding the port; Kubernetes/Docker port conflicts; misconfigured bindAddress; invalid keystore config for the TLS connector.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/56d82e208267f71b. Report an issue: GitHub.