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').

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)

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.