languagetool-org/languagetool · critical · PortBindingException
http_server_start_failed
Error message
http_server_start_failed
What it means
HTTPServer's constructor wraps listener setup failures: when the server cannot bind to host:port (or another exception occurs during startup), it throws PortBindingException with the localized 'http_server_start_failed' message. Same port-binding failure family as the HTTPS server, but for plain HTTP.
Source
Thrown at languagetool-server/src/main/java/org/languagetool/server/HTTPServer.java:128
httpHandler = new LanguageToolHttpHandler(config, allowedIps, runInternally, limiter, errorLimiter, workQueue, this);
//check if port is 0 for get random port from range
if (port == 0) {
int minPort = config.getMinPort();
int maxPort = config.getMaxPort();
port = getPortFromRange(minPort, maxPort);
}
InetSocketAddress address = host != null ? new InetSocketAddress(host, port) : new InetSocketAddress(port);
server = HttpServer.create(address, 0);
server.createContext("/", httpHandler);
server.setExecutor(executorService);
if (config.isPrometheusMonitoring()) {
ServerMetricsCollector.init(config);
}
} catch (Exception e) {
ResourceBundle messages = JLanguageTool.getMessageBundle();
String message = Tools.i18n(messages, "http_server_start_failed", host, Integer.toString(port));
throw new PortBindingException(message, e);
}
}
private int getPortFromRange(int minPort, int maxPort) throws IOException {
if (minPort > 0 && minPort < maxPort) {
log.info("Try to find a free Port for Server in range {}-{}", minPort, maxPort);
for (int p = minPort; p <= maxPort; p++) {
try {
log.info("Check port {}", p);
ServerSocket serverSocket = new ServerSocket(p);
port = serverSocket.getLocalPort();
serverSocket.close();
log.info("Port {} is available.", p);
return p;
} catch (IOException ex) {
log.debug("Port {} is not available.", p);
}
}View on GitHub (pinned to 2e990059ce)
Solutions
- Identify and stop the process holding the port: lsof -i :<port> / ss -ltnp.
- Change the configured port or widen the port range in the config.
- Kill stale LT server processes (ps aux | grep languagetool).
- Verify the host/interface value in config matches an address available on the machine.
Example fix
// before port = 8080 // occupied by nginx // after port = 8081 # or stop nginx on 8080 first
Defensive patterns
Strategy: try-catch
Validate before calling
// check port availability before startup
try (ServerSocket s = new ServerSocket()) {
s.bind(new InetSocketAddress(host, port));
} catch (IOException e) {
throw new IllegalStateException("HTTP port " + port + " already in use");
} Try / catch
try {
httpServer = new HTTPServer(config, false, allowedIps);
} catch (PortBindingException e) {
log.error("HTTP port {} in use", config.getPort(), e);
System.exit(1);
} Prevention
- Reserve distinct ports for each service instance
- Use the port-range config so the server auto-picks a free port
- Check for stale processes after crashes before restart
- Validate container/host port mappings don't overlap
When it happens
Trigger: Starting the HTTP server on a port already in use (BindException); binding to a host address not present on the machine; port-range exhaustion if getPortFromRange cannot find a free port.
Common situations: Another LT instance or other service already on the port; Docker port conflicts; stale process from a crashed run; min/max port range fully occupied in auto-port mode.
Related errors
- https_server_start_failed
- Could not start LanguageTool HTTPS server on , port
- No free port in range ( - ) found.
- Could not load remote rules configuration at <configFile.get
- Invalid userInfo format, expected 'user:password':
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/d134f151f0763643.
Report an issue: GitHub.