Tencent/VasSonic · error · SSLException

Cannot verify SSL socket without session

Error message

Cannot verify SSL socket without session

What it means

After starting the handshake for SNI hostname verification, verifyHostname() fetches the SSLSession and throws SSLException if the session is null — without a session there are peer certificates to verify against.

Solutions

  1. Retry the request; a null session usually indicates a transient handshake failure on mobile networks
  2. Check server TLS compatibility (supported protocol versions/ciphers) and enable TLSv1.2 explicitly via ssl.setEnabledProtocols
  3. Verify no custom SSL implementation overrides getSession() incorrectly
  4. Log and surface the underlying handshake exception from startHandshake() to diagnose the root cause

Example fix

// before
ssl.startHandshake();
SonicSniSSLSocketFactory.verifyHostname(socket, host);
// after
ssl.setEnabledProtocols(new String[]{"TLSv1.2"});
try {
  ssl.startHandshake();
} catch (IOException e) {
  throw new SSLException("Handshake failed for " + host, e);
}
Defensive patterns

Strategy: retry

Validate before calling

try { ssl.startHandshake(); } catch (IOException e) {
  throw new SSLException("Handshake failed, session unavailable for " + host, e);
} // only proceed if handshake succeeded

Type guard

// Java
static boolean hasSession(SSLSocket ssl) {
  return ssl.getSession() != null;
}

Try / catch

try {
  SonicSniSSLSocketFactory.verifyHostname(socket, host);
} catch (SSLException e) {
  // transient handshake failure: retry request or surface a network error
}

Prevention

When it happens

Trigger: ssl.getSession() returns null after startHandshake(), which happens when the TLS handshake failed or was aborted before a session was established (e.g. handshake interrupted, SSL library error swallowed, or a non-standard SSLSocket implementation).

Common situations: Servers abruptly closing the connection during handshake; TLS version/cipher mismatch with the server; custom SSLSocket implementations that don't populate the session; low-level network errors during the handshake on flaky mobile networks.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Tencent/VasSonic@59936beff6 (2026-09-08). Data as JSON: /api/errors/d1dbfafdc258c4dc. Report an issue: GitHub.

Appendix: source

Thrown at sonic-android/sdk/src/main/java/com/tencent/sonic/sdk/SonicSniSSLSocketFactory.java:187

     * @param socket An SSL socket which has been connected to a server
     * @param hostname The expected hostname of the remote server
     * @throws IOException if something goes wrong handshaking with the server
     * @throws SSLPeerUnverifiedException if the server cannot prove its identity
     *
     */
    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)