languagetool-org/languagetool · critical · RuntimeException

Could not set up SSL context

Error message

Could not set up SSL context

What it means

getSslContext loads the JKS keystore, builds KeyManagerFactory/TrustManagerFactory and initializes a TLS SSLContext; any Exception in that chain (file not found, wrong password, bad keystore format, missing TLS provider) is rethrown as RuntimeException('Could not set up SSL context').

Solutions

  1. Verify the keystore file path exists and is readable by the server process.
  2. Confirm the file is really JKS format; convert if needed with keytool -importkeystore.
  3. Check the 'password' property matches the keystore's password.
  4. Validate the keystore with: keytool -list -keystore server.jks.
  5. Update to a JDK that supports the required TLS version/algorithms.

Example fix

// before
keystore = /etc/ssl/cert.pem   // PEM, not JKS
// after
keytool -importkeystore -srckeystore cert.pem -destkeystore server.jks -deststoretype JKS
# server.properties
keystore = /etc/ssl/server.jks
Defensive patterns

Strategy: try-catch

Validate before calling

// validate keystore before starting server
KeyStore ks = KeyStore.getInstance("JKS");
try (FileInputStream in = new FileInputStream(keystoreFile)) {
  ks.load(in, password.toCharArray()); // throws here, before server start
}

Try / catch

try {
  server = new HTTPSServer(config, false, host, ips);
} catch (RuntimeException e) {
  if (e.getMessage().contains("SSL context")) {
    log.error("Check keystore path/format/password: {}", e.getCause());
  }
}

Prevention

When it happens

Trigger: Keystore file does not exist or is unreadable; keystore is not a valid JKS file; password is wrong; JDK lacks the SunX509/TLS algorithms (unusual JVM/provider).

Common situations: Config points to a PEM file instead of JKS; typos in keystore path in server.properties; PKCS12 file renamed to .jks; corrupted keystore.

Understand the failure class

Related errors


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

Appendix: source

Thrown at languagetool-server/src/main/java/org/languagetool/server/HTTPSServer.java:101

      ResourceBundle messages = JLanguageTool.getMessageBundle();
      String message = Tools.i18n(messages, "https_server_start_failed_unknown_reason", host, Integer.toString(port));
      throw new RuntimeException(message, e);
    }
  }

  private SSLContext getSslContext(File keyStoreFile, String passPhrase) {
    try (FileInputStream keyStoreStream = new FileInputStream(keyStoreFile)) {
      KeyStore keystore = KeyStore.getInstance("JKS");
      keystore.load(keyStoreStream, passPhrase.toCharArray());
      KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
      kmf.init(keystore, passPhrase.toCharArray());
      TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
      tmf.init(keystore);
      SSLContext sslContext = SSLContext.getInstance("TLS");
      sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
      return sslContext;
    } catch (Exception e) {
      throw new RuntimeException("Could not set up SSL context", e);
    }
  }

  private HttpsConfigurator getConfigurator(SSLContext sslContext) {
    return new HttpsConfigurator(sslContext) {
          @Override
          public void configure (HttpsParameters params) {
            SSLContext context = getSSLContext();
            SSLParameters sslParams = context.getDefaultSSLParameters();
            params.setNeedClientAuth(false);
            params.setSSLParameters(sslParams);
          }
        };
  }

  @Override
  public void stop() {
    super.stop();

View on GitHub (pinned to 2e990059ce)