Tencent/VasSonic · error · SSLPeerUnverifiedException
Cannot verify hostname:
Error message
Cannot verify hostname:
What it means
After obtaining the SSLSession, verifyHostname() runs the default HttpsURLConnection hostname verifier against it. If verification fails (certificate CN/SAN doesn't match the requested hostname), it throws SSLPeerUnverifiedException — protecting against MITM and hostname mismatches.
Solutions
- Access the server using a hostname that exactly matches a SAN entry in its certificate
- Fix the server certificate to include the hostname (add SAN entries) and redeploy
- Remove IP-based URLs or custom host mappings that bypass proper hostname matching
- If intentional (e.g. test environments), install a custom HostnameVerifier — but never disable verification in production
Example fix
// before
URL url = new URL("https://10.0.0.5/api"); // cert has no IP SAN -> throws
// after
URL url = new URL("https://api.example.com/api"); // matches cert SAN Defensive patterns
Strategy: try-catch
Validate before calling
Certificate[] certs = ssl.getSession().getPeerCertificates(); // check that host matches a SAN entry before connecting // e.g. hostname must equal one of the dNSName SANs in certs[0]
Try / catch
try {
SonicSniSSLSocketFactory.verifyHostname(socket, host);
} catch (SSLPeerUnverifiedException e) {
// hostname mismatch: do NOT proceed; alert or use the cert-matching hostname
} Prevention
- Never connect by raw IP address for HTTPS unless the cert has an IP SAN
- Keep server certificates' SAN entries in sync with all hostnames/aliases used
- Test staging environments with certs matching the hostnames actually used
When it happens
Trigger: The server presents a valid certificate that does not match the hostname used in the request — connecting by IP address, a hostname not in the cert's SAN, an internal hostname fronted by a generic cert, or DNS pointing to a different server.
Common situations: Hitting a server via its IP or an alias not listed in the certificate; expired/reissued certs missing the old SAN entries; proxies/gateways serving the wrong cert; testing against a staging server using production certs.
Related errors
AI-assisted analysis of Tencent/VasSonic@59936beff6 (2026-09-08).
Data as JSON: /api/errors/e364fa1c817abc9a.
Report an issue: GitHub.
Appendix: source
Thrown at sonic-android/sdk/src/main/java/com/tencent/sonic/sdk/SonicSniSSLSocketFactory.java:192
*/
public static void verifyHostname(Socket socket, String hostname) throws IOException {
if (!(socket instanceof SSLSocket)) {
throw new IllegalArgumentException("Attempt to verify non-SSL socket");
}
// The code at the start of OpenSSLSocketImpl.startHandshake()
// ensures that the call is idempotent, so we can safely call it.
SSLSocket ssl = (SSLSocket) socket;
ssl.startHandshake();
SSLSession session = ssl.getSession();
if (session == null) {
throw new SSLException("Cannot verify SSL socket without session");
}
if (!HttpsURLConnection.getDefaultHostnameVerifier().verify(hostname, session)) {
SonicUtils.log(TAG, Log.ERROR, "sonic SSL error:Cannot verify hostname" + hostname + ")!");
throw new SSLPeerUnverifiedException("Cannot verify hostname: " + hostname);
}
}
}
View on GitHub (pinned to 59936beff6)