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

  1. Identify and stop the process holding the port: lsof -i :<port> / ss -ltnp.
  2. Change the configured port or widen the port range in the config.
  3. Kill stale LT server processes (ps aux | grep languagetool).
  4. 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

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


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/d134f151f0763643. Report an issue: GitHub.