prestodb/presto · error · GeneralSecurityException

Loaded truststore is empty - no certificates found in:

Error message

Loaded truststore is empty - no certificates found in: 

What it means

SslContextProvider.loadTrustStore validates that the KeyStore it just loaded from trustStorePath actually contains at least one certificate alias. If Collections.list(trustStore.aliases()) is empty, the truststore file exists but holds no entries, so it cannot be used to build an SSLContext; a GeneralSecurityException is thrown to fail fast instead of producing a trust manager that trusts nothing and causes opaque handshake failures later.

Source

Thrown at presto-plugin-toolkit/src/main/java/com/facebook/presto/plugin/base/security/SslContextProvider.java:253

                try (InputStream inputStream = Files.newInputStream(trustStorePath.toPath())) {
                    trustStore.load(inputStream, trustStorePassword.map(String::toCharArray).orElse(null));
                }
                log.debug("Successfully loaded truststore as JKS format");
            }
            catch (IOException | GeneralSecurityException e) {
                log.debug("Failed to load truststore as JKS format: {}", e.getMessage());
                throw new GeneralSecurityException(
                        "Failed to load truststore as both PEM and KeyStore format. " +
                                "PEM error: " + (lastException != null ? lastException.getMessage() : "unknown") +
                                ", KeyStore error: " + e.getMessage(), e);
            }
        }

        // Verify the truststore is not empty
        try {
            List<String> aliases = Collections.list(trustStore.aliases());
            if (aliases.isEmpty()) {
                throw new GeneralSecurityException("Loaded truststore is empty - no certificates found in: " + trustStorePath);
            }
            log.debug("Truststore loaded with {} certificate(s)", aliases.size());
        }
        catch (KeyStoreException e) {
            throw new GeneralSecurityException("Failed to verify truststore contents", e);
        }

        return trustStore;
    }

    private static void validateCertificates(KeyStore keyStore) throws GeneralSecurityException
    {
        for (String alias : list(keyStore.aliases())) {
            if (!keyStore.isKeyEntry(alias)) {
                continue;
            }

            Certificate certificate = keyStore.getCertificate(alias);

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Import a CA certificate into the truststore: keytool -importcert -alias ca -file ca.pem -keystore truststore.jks -storepass <pass>
  2. Verify the file is non-empty and a real KeyStore: keytool -list -keystore <path> -storepass <pass>; it should list at least one alias
  3. If the file is PEM-only, convert it to PKCS12 first (openssl pkcs12 -export or use a PEM-trusting SSLContext option) instead of passing it as a JKS
  4. Check the truststorePath config property points at the intended file, not a placeholder created by setup scripts

Example fix

// before
createSSLContext(configWithEmptyTrustStore);
// after
// populate the truststore first:
// keytool -importcert -alias myca -file ca.crt -keystore truststore.jks
createSSLContext(validatedConfig);
Defensive patterns

Strategy: validation

Validate before calling

java
KeyStore ts = KeyStore.getInstance("JKS");
try (InputStream in = Files.newInputStream(Paths.get(trustStorePath))) {
    ts.load(in, password);
}
if (Collections.list(ts.aliases()).isEmpty()) {
    throw new IllegalStateException("Truststore has no certificates: " + trustStorePath);
}

Type guard

java
static boolean hasCertificates(KeyStore ks) throws KeyStoreException {
    return ks != null && ks.size() > 0;
}

Try / catch

java
try {
    sslContext = provider.createSSLContext(config);
} catch (GeneralSecurityException e) {
    log.error("Truststore problem: " + e.getMessage());
    throw new IllegalStateException("Fix truststore configuration before starting", e);
}

Prevention

When it happens

Trigger: Calling createSSLContext (via loadTrustStore) with a truststore file that was loaded successfully but has zero aliases — e.g. an empty file, a file created with `keytool -genkeypair` that was later deleted, or a file in the wrong format whose entries were silently dropped.

Common situations: Pointing config at a truststore path that was never populated (0-byte file), using a PEM file where a JKS/PKCS12 file is expected so load succeeds but no entries parse, overwriting a truststore during a cert rotation with an empty keytool import, or container image builds that create the file but skip the certificate-import step.

Understand the failure class

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/e937225baa2e2c44. Report an issue: GitHub.