elastic/elasticsearch · error · SslConfigException

Unexpected error initializing a new in-memory keystore

Error message

Unexpected error initializing a new in-memory keystore

What it means

Thrown by KeyStoreUtil.buildNewKeyStore() when KeyStore.load(null, null) — initializing an empty in-memory keystore — unexpectedly raises an IOException. The code considers this a 'should never happen' path: loading an empty keystore with no input stream normally cannot fail, so the exception is wrapped in SslConfigException to relieve callers from declaring IOException.

Source

Thrown at libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/KeyStoreUtil.java:134

        int counter = 0;
        for (Certificate certificate : certificates) {
            store.setCertificateEntry("cert-" + counter, certificate);
            counter++;
        }
        return store;
    }

    private static KeyStore buildNewKeyStore() throws GeneralSecurityException {
        return buildNewKeyStore(KeyStore.getDefaultType());
    }

    private static KeyStore buildNewKeyStore(String type) throws GeneralSecurityException {
        KeyStore keyStore = KeyStore.getInstance(type);
        try {
            keyStore.load(null, null);
        } catch (IOException e) {
            // This should never happen so callers really shouldn't be forced to deal with it themselves.
            throw new SslConfigException("Unexpected error initializing a new in-memory keystore", e);
        }
        return keyStore;
    }

    /**
     * Returns a {@link X509ExtendedKeyManager} that is built from the provided private key and certificate chain
     */
    public static X509ExtendedKeyManager createKeyManager(Certificate[] certificateChain, PrivateKey privateKey, char[] password)
        throws GeneralSecurityException, IOException {
        KeyStore keyStore = buildKeyStore(List.of(certificateChain), privateKey, password);
        return createKeyManager(keyStore, password, KeyManagerFactory.getDefaultAlgorithm());
    }

    /**
     * Creates a {@link X509ExtendedKeyManager} based on the key material in the provided {@link KeyStore}
     */
    public static X509ExtendedKeyManager createKeyManager(KeyStore keyStore, char[] password, String algorithm)
        throws GeneralSecurityException {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the wrapped cause (SslConfigException.getCause()) — it carries the real IOException from the provider.
  2. Verify the default keystore type: check `KeyStore.getDefaultType()` and the `keystore.type` entry in `java.security`.
  3. On FIPS/BCFIPS, follow Elastic's FIPS documentation to configure the keystore type and provider correctly.
  4. Try a fresh JVM/JDK install if the JCE configuration is corrupted.

Example fix

// before: relying on default keystore type in a constrained JVM
KeyStore ks = KeyStoreUtil.buildKeyStore(certs, key, pwd); // wraps IOException

// after: explicit type aligned with the available provider
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(null, null);
ks.setKeyEntry("key", key, pwd, certs.toArray(new Certificate[0]));
Defensive patterns

Strategy: try-catch

Validate before calling

// Smoke-test that an empty keystore of the configured type can be initialised.
public static boolean canInitEmptyKeyStore(String type) {
    try {
        KeyStore ks = KeyStore.getInstance(type);
        ks.load(null, null);
        return true;
    } catch (Exception e) {
        return false;
    }
}

Try / catch

try {
    return KeyStoreUtil.buildKeyStore(certChain, key, pwd);
} catch (SslConfigException e) {
    // getCause() is the original IOException from KeyStore.load
    log.error("keystore init failed; check default keystore type and JCE provider", e.getCause());
    throw e;
}

Prevention

When it happens

Trigger: buildNewKeyStore(type) calls KeyStore.getInstance(type).load(null, null). On rare JVMs or with non-default security providers, the no-arg load can fail — e.g. a provider that demands an actual input stream, a corrupted JCE configuration, or a SecurityManager/manager-policy rejection.

Common situations: Custom JCE provider registered as default keystore type that does not support empty init; classpath/module issues loading the keystore SPI; FIPS-mode JVM (BCFIPS) where the default type behaves differently; or a JVM that has been misconfigured (java.security corrupted).

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/165d98ffb4a0ca02. Report an issue: GitHub.