{"record":{"id":"e937225baa2e2c44","repo":"prestodb/presto","slug":"loaded-truststore-is-empty-no-certificates-found","errorCode":null,"errorMessage":"Loaded truststore is empty - no certificates found in: ","messagePattern":"Loaded truststore is empty - no certificates found in: ","errorType":"exception","errorClass":"GeneralSecurityException","httpStatus":null,"severity":"error","filePath":"presto-plugin-toolkit/src/main/java/com/facebook/presto/plugin/base/security/SslContextProvider.java","lineNumber":253,"sourceCode":"                try (InputStream inputStream = Files.newInputStream(trustStorePath.toPath())) {\n                    trustStore.load(inputStream, trustStorePassword.map(String::toCharArray).orElse(null));\n                }\n                log.debug(\"Successfully loaded truststore as JKS format\");\n            }\n            catch (IOException | GeneralSecurityException e) {\n                log.debug(\"Failed to load truststore as JKS format: {}\", e.getMessage());\n                throw new GeneralSecurityException(\n                        \"Failed to load truststore as both PEM and KeyStore format. \" +\n                                \"PEM error: \" + (lastException != null ? lastException.getMessage() : \"unknown\") +\n                                \", KeyStore error: \" + e.getMessage(), e);\n            }\n        }\n\n        // Verify the truststore is not empty\n        try {\n            List<String> aliases = Collections.list(trustStore.aliases());\n            if (aliases.isEmpty()) {\n                throw new GeneralSecurityException(\"Loaded truststore is empty - no certificates found in: \" + trustStorePath);\n            }\n            log.debug(\"Truststore loaded with {} certificate(s)\", aliases.size());\n        }\n        catch (KeyStoreException e) {\n            throw new GeneralSecurityException(\"Failed to verify truststore contents\", e);\n        }\n\n        return trustStore;\n    }\n\n    private static void validateCertificates(KeyStore keyStore) throws GeneralSecurityException\n    {\n        for (String alias : list(keyStore.aliases())) {\n            if (!keyStore.isKeyEntry(alias)) {\n                continue;\n            }\n\n            Certificate certificate = keyStore.getCertificate(alias);","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-plugin-toolkit/src/main/java/com/facebook/presto/plugin/base/security/SslContextProvider.java#L235-L271","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Import a CA certificate into the truststore: keytool -importcert -alias ca -file ca.pem -keystore truststore.jks -storepass <pass>","Verify the file is non-empty and a real KeyStore: keytool -list -keystore <path> -storepass <pass>; it should list at least one alias","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","Check the truststorePath config property points at the intended file, not a placeholder created by setup scripts"],"exampleFix":"// before\ncreateSSLContext(configWithEmptyTrustStore);\n// after\n// populate the truststore first:\n// keytool -importcert -alias myca -file ca.crt -keystore truststore.jks\ncreateSSLContext(validatedConfig);","handlingStrategy":"validation","validationCode":"java\nKeyStore ts = KeyStore.getInstance(\"JKS\");\ntry (InputStream in = Files.newInputStream(Paths.get(trustStorePath))) {\n    ts.load(in, password);\n}\nif (Collections.list(ts.aliases()).isEmpty()) {\n    throw new IllegalStateException(\"Truststore has no certificates: \" + trustStorePath);\n}","typeGuard":"java\nstatic boolean hasCertificates(KeyStore ks) throws KeyStoreException {\n    return ks != null && ks.size() > 0;\n}","tryCatchPattern":"java\ntry {\n    sslContext = provider.createSSLContext(config);\n} catch (GeneralSecurityException e) {\n    log.error(\"Truststore problem: \" + e.getMessage());\n    throw new IllegalStateException(\"Fix truststore configuration before starting\", e);\n}","preventionTips":["Run keytool -list -keystore <path> as a startup/CI sanity check","Generate truststores in a setup script that fails if the certificate import fails","Never commit placeholder 0-byte truststore files","Use PKCS12 format and import the full CA chain"],"tags":["ssl","truststore","security","configuration"],"backgroundTag":"empty-truststore","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}