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.

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.

Appendix: 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)