alibaba/canal · critical · CertificateException
Can't verify server certificate because no trust manager is
Error message
Can't verify server certificate because no trust manager is found.
What it means
Thrown inside the X509TrustManagerWrapper.checkServerTrusted when verifyServerCert is true (VERIFY_CA/VERIFY_IDENTITY) but origTm is null, i.e. no backing X509TrustManager was supplied. The wrapper cannot validate the server certificate chain against any trust store, so it refuses to trust. This is the 'I was asked to verify but have nothing to verify against' failure.
Source
Thrown at driver/src/main/java/com/alibaba/otter/canal/parse/driver/mysql/socket/BioSocketChannelPool.java:280
try {
CertPath certPath = this.certFactory.generateCertPath(Arrays.asList(chain));
// Validate against truststore
CertPathValidatorResult result = this.validator.validate(certPath, this.validatorParams);
// Check expiration for the CA used to validate this path
((PKIXCertPathValidatorResult) result).getTrustAnchor().getTrustedCert().checkValidity();
} catch (InvalidAlgorithmParameterException e) {
throw new CertificateException(e);
} catch (CertPathValidatorException e) {
throw new CertificateException(e);
}
}
if (this.verifyServerCert) {
if (this.origTm != null) {
this.origTm.checkServerTrusted(chain, authType);
} else {
throw new CertificateException(
"Can't verify server certificate because no trust manager is found.");
}
// verify server certificate identity
if (this.hostName != null) {
logger.info("verify hostName: {}", this.hostName);
Set<String> expectHostNames = new HashSet<>();
for (X509Certificate certificate : chain) {
String dn = certificate.getSubjectX500Principal().getName(X500Principal.RFC2253);
String cn = null;
try {
LdapName ldapDN = new LdapName(dn);
for (Rdn rdn : ldapDN.getRdns()) {
if (rdn.getType().equalsIgnoreCase("CN")) {
cn = rdn.getValue().toString();
break;
}
}View on GitHub (pinned to 87be50e876)
Solutions
- Provide a valid trustCertificateKeyStoreUrl (and type/password) pointing to a JKS/PKCS12 store containing the MySQL server's CA.
- Ensure the JVM default cacerts is present and populated when relying on fallbackToDefaultTrustStore.
- Verify the truststore URL is reachable and the type matches the file format (JKS vs PKCS12).
- If you intentionally cannot verify, use SslMode.REQUIRED instead of VERIFY_CA/VERIFY_IDENTITY.
Example fix
// before
SslInfo info = new SslInfo();
info.setSslMode(SslMode.VERIFY_CA);
// no trust store set -> handshake throws
// after
info.setTrustCertificateKeyStoreUrl("file:/etc/canal/truststore.jks");
info.setTrustCertificateKeyStoreType("JKS");
info.setTrustCertificateKeyStorePassword("changeit"); Defensive patterns
Strategy: validation
Validate before calling
boolean verify = mode == SslMode.VERIFY_CA || mode == SslMode.VERIFY_IDENTITY;
boolean hasTrustStore = StringUtils.isNotEmpty(sslInfo.getTrustCertificateKeyStoreUrl());
if (verify && !hasTrustStore) {
// ensure default cacerts exists, else fail fast with a clear message
} Type guard
public static boolean canVerify(SslInfo info) {
SslMode m = info.getSslMode();
if (m != SslMode.VERIFY_CA && m != SslMode.VERIFY_IDENTITY) return true;
return StringUtils.isNotEmpty(info.getTrustCertificateKeyStoreUrl())
|| defaultCacertsExists();
} Try / catch
try {
socketFactory.createSocket(...).startHandshake();
} catch (javax.net.ssl.SSLHandshakeException e) {
if (e.getMessage().contains("no trust manager")) {
// configure trustCertificateKeyStoreUrl or use REQUIRED
}
throw e;
} Prevention
- Supply a valid trustCertificateKeyStoreUrl for VERIFY_CA/VERIFY_IDENTITY.
- Confirm the JVM default cacerts is present when relying on fallback.
- Use SslMode.REQUIRED when you cannot supply a trust store.
When it happens
Trigger: Constructing an X509TrustManagerWrapper with a null origTm (the verifyServerCert-only constructor) and then calling checkServerTrusted; or the trust-manager list built in getSSLContext having no X509TrustManager to delegate to. Triggered during SSL handshake when VERIFY_CA/VERIFY_IDENTITY is set without a usable trust store.
Common situations: VERIFY_CA/VERIFY_IDENTITY configured but no trustCertificateKeyStoreUrl supplied and the default JVM truststore (cacerts) is empty/missing; the fallback wrapper path was taken (tms.size()==0 branch) and verification was requested; misconfigured truststore URL/type/password that produced no X509TrustManager.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- Failed to retrieve the Common Name (CN) from the server cert
- Server certificate identity check failed. The certificate Co
- Unsupported ssl mode: {}
- canal socketChannel netty not support ssl mode: {}
- connect failure
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/a3e21de67e2c1355.
Report an issue: GitHub.