prestodb/presto · error · RuntimeException
Expected exactly one X509TrustManager, but found: ${trustMan
Error message
Expected exactly one X509TrustManager, but found: ${trustManagers} What it means
When building the TLS context for a secured metastore connection, the factory initializes a TrustManagerFactory from the configured truststore and requires exactly one X509TrustManager. If the truststore yields zero or multiple trust managers, or a non-X509 one, the JDK default algorithm produced something unexpected, so a RuntimeException is thrown rather than proceeding with ambiguous trust settings.
Source
Thrown at presto-hive-metastore/src/main/java/com/facebook/presto/hive/metastore/thrift/HiveMetastoreClientFactory.java:152
final KeyManagerFactory metastoreKeyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
metastoreKeyManagerFactory.init(metastoreKeyStore, keyManagerPassword);
metastoreKeyManagers = metastoreKeyManagerFactory.getKeyManagers();
}
// load TrustStore if configured, otherwise use KeyStore
KeyStore metastoreTrustStore = metastoreKeyStore;
if (truststorePath.isPresent()) {
metastoreTrustStore = getTrustStore(truststorePath.get(), trustStorePassword);
}
// create TrustManagerFactory
final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(metastoreTrustStore);
// get X509TrustManager
final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new RuntimeException("Expected exactly one X509TrustManager, but found:" + Arrays.toString(trustManagers));
}
// create SSLContext
final SSLContext sslContext = SSLContext.getInstance(PROTOCOL);
sslContext.init(metastoreKeyManagers, trustManagers, null);
return Optional.of(sslContext);
}
catch (GeneralSecurityException | IOException e) {
throw new PrestoException(HIVE_METASTORE_INITIALIZE_SSL_ERROR, e);
}
}
/**
* Reads the truststore certificate and returns it
*
* @param trustStorePath
* @param trustStorePassword
* @throws IOExceptionView on GitHub (pinned to 55bb57d202)
Solutions
- Use a truststore containing only trusted CA certificates (keytool -import -trustcacerts), not a keystore with keys.
- Verify the truststore loads and contains entries: keytool -list -v -keystore truststore.jks.
- Set the store type explicitly to match the file (e.g. -Dhive.metastore.thrift.ssl.truststore.type=JKS/PKCS12).
- Remove non-standard security providers from java.security or run on a standard JDK.
- If a custom TrustManagerFactory is required, ensure it returns exactly one X509TrustManager.
Example fix
// before # truststore is actually a keystore with private keys hive.metastore.thrift.ssl.truststore=/etc/hive/server.keystore // after keytool -importcert -alias corporate-ca -file corp-ca.pem -keystore truststore.jks hive.metastore.thrift.ssl.truststore=/etc/hive/truststore.jks
Defensive patterns
Strategy: validation
Validate before calling
// validate truststore before enabling metastore SSL
KeyStore ts = KeyStore.getInstance("JKS");
try (InputStream in = Files.newInputStream(Paths.get(truststorePath))) {
ts.load(in, truststorePassword);
}
int certs = Collections.list(ts.aliases()).size();
if (certs != 1) {
throw new IllegalStateException("truststore must contain exactly one CA cert, found " + certs);
} Try / catch
try {
HiveMetastoreClient client = clientFactory.create(...);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("Expected exactly one X509TrustManager")) {
// fix truststore contents/type, then retry
} else {
throw e;
}
} Prevention
- Keep a dedicated truststore holding only CA certs, separate from identity keystores
- Validate store contents with keytool -list after every rotation
- Pin the JVM's security providers; avoid exotic JCE providers on Presto nodes
- Match store type flags (JKS/PKCS12) to the actual file format
- Add truststore load checks to deployment smoke tests
When it happens
Trigger: hive.metastore.thrift.ssl.truststore configured with a store containing multiple/zero certificate entries, or a JVM/provider whose default TrustManagerFactory returns several TrustManagers (e.g. unusual security providers or a truststore of an unsupported type).
Common situations: Using a keystore (.jks with private keys) as the truststore by mistake; truststore file corrupt or empty; custom JCE providers installed; mixing PKCS12/JKS types; vendor JVMs with multiple trust managers.
Related errors
- Unexpected default trust managers:
- HIVE_METASTORE_INITIALIZE_SSL_ERROR
- KeyStore certificate is expired: ${e.getMessage()}
- Truststore is empty - no trusted certificates found
- Error setting up SSL:
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/bece69645361a0de.
Report an issue: GitHub.