apache/seatunnel · error · RuntimeException
Unexpected default trust managers:
Error message
Unexpected default trust managers:
What it means
SSLUtils.createSSLContext initializes the default TrustManagerFactory from the configured trust store and expects it to yield exactly one TrustManager that is an X509TrustManager. If the JDK/security provider returns a different set (multiple managers or a non-X509 type), this RuntimeException is thrown because the code cannot build the SSLContext it needs for HTTPS connections to Elasticsearch.
Source
Thrown at seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/util/SSLUtils.java:111
keyManagers = keyManagerFactory.getKeyManagers();
}
// load TrustStore if configured, otherwise use KeyStore
KeyStore trustStore = keyStore;
if (trustStorePath.isPresent()) {
File trustStoreFile = new File(trustStorePath.get());
trustStore = loadTrustStore(trustStoreFile, trustStorePassword);
}
// create TrustManagerFactory
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
// get X509TrustManager
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new RuntimeException(
"Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
// create SSLContext
SSLContext result = SSLContext.getInstance("SSL");
result.init(keyManagers, trustManagers, null);
return result;
}
private static KeyStore loadTrustStore(File trustStorePath, Optional<String> trustStorePassword)
throws IOException, GeneralSecurityException {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
try {
// attempt to read the trust store as a PEM file
List<X509Certificate> certificateChain = PemReader.readCertificateChain(trustStorePath);
if (!certificateChain.isEmpty()) {
trustStore.load(null, null);
for (X509Certificate certificate : certificateChain) {
X500Principal principal = certificate.getSubjectX500Principal();View on GitHub (pinned to cf67b549a7)
Solutions
- Run on a standard Oracle/OpenJDK/Temurin JDK with the default SUN security provider, where the default algorithm yields a single X509TrustManager.
- Check java.security (securerandom/source and ssl.TrustManagerFactoryAlgorithm overrides) and remove custom TrustManagerFactory algorithm overrides.
- If a FIPS or IBM JDK is required, supply a custom trust manager wrapper that picks the X509TrustManager from the array instead of relying on this utility.
- Inspect the exception's Arrays.toString(trustManagers) output to identify which provider returned the unexpected managers.
Example fix
// before (JDK with multiple trust managers)
SSLContext ctx = SSLUtils.buildSSLContext(trustStore, keyStore, password);
// after (pick the X509TrustManager explicitly in a custom utility)
X509TrustManager x509 = (X509TrustManager) Arrays.stream(trustManagerFactory.getTrustManagers())
.filter(tm -> tm instanceof X509TrustManager).findFirst()
.orElseThrow(() -> new RuntimeException("No X509TrustManager found"));
sslContext.init(keyManagers, new TrustManager[]{x509}, null); Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the default trust managers before building the SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore) null);
for (TrustManager tm : tmf.getTrustManagers()) {
if (!(tm instanceof X509TrustManager)) {
throw new IllegalStateException("Provider returns non-X509 trust managers: " + tm);
}
} Type guard
boolean hasSingleX509TrustManager(TrustManager[] tms) {
return tms != null && tms.length == 1 && tms[0] instanceof X509TrustManager;
} Try / catch
try {
SSLContext ctx = SSLUtils.buildSSLContext(trustStore, keyStore, password);
} catch (RuntimeException e) {
if (e.getMessage().startsWith("Unexpected default trust managers")) {
log.error("JDK/security provider returned unsupported TrustManagers; switch to a standard JDK", e);
}
throw e;
} Prevention
- Use standard OpenJDK/Temurin builds without FIPS or custom security providers for SeaTunnel workers.
- Do not override ssl.TrustManagerFactoryAlgorithm in java.security.
- Log the TrustManager array from getTrustManagers() when configuring SSL to detect provider issues early.
When it happens
Trigger: Calling buildSSLContext when trustManagerFactory.getTrustManagers() returns an array with length != 1 or whose first element is not an X509TrustManager. Happens with unusual JCE security providers, custom crypto setups (e.g. IBM JDK, FIPS providers), or exotic trust store configurations.
Common situations: Running on a JDK or security provider (FIPS-enabled JVM, IBM JDK, custom java.security file) that registers multiple trust managers; corrupt or non-standard trust store entries; exotic SSL configurations in containerized environments.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- Failed to configure TLS settings
- Could not load keystore
- Could not load truststore
- Unexpected default trust managers:
- KeyStore certificate is expired:
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/e34a46140c6141f3.
Report an issue: GitHub.