didi/DoKit · error · IllegalStateException

Connection has not yet been established

Error message

Connection has not yet been established

What it means

OkHttpsURLConnection.handshake() exposes the TLS handshake of the underlying OkHttp call; delegate.call is only created inside buildCall(), so calling getServerCertificates()/handshake before the connection was established throws IllegalStateException("Connection has not yet been established"). There is no handshake to report until the request has been sent.

Source

Thrown at Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java:1291

        }
    }

    static final class OkHttpsURLConnection extends DelegatingHttpsURLConnection {
        private final OkHttpURLConnection delegate;

        OkHttpsURLConnection(URL url, OkHttpClient client) {
            this(new OkHttpURLConnection(url, client));
        }

        OkHttpsURLConnection(OkHttpURLConnection delegate) {
            super(delegate);
            this.delegate = delegate;
        }

        @Override
        protected Handshake handshake() {
            if (delegate.call == null) {
                throw new IllegalStateException("Connection has not yet been established");
            }

            return delegate.handshake;
        }

        @Override
        public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
            delegate.client = delegate.client.newBuilder()
                    .hostnameVerifier(hostnameVerifier)
                    .build();
        }

        @Override
        public HostnameVerifier getHostnameVerifier() {
            return delegate.client.hostnameVerifier();
        }

        @Override

View on GitHub (pinned to 626827cddb)

Solutions

  1. Trigger the connection first (connect() or getResponseCode()), then read the handshake.
  2. For pinning, prefer OkHttp's CertificatePinner configured on the client rather than manual handshake inspection.
  3. Restructure the check into a response interceptor or after getInputStream().

Example fix

// before
HttpsURLConnection hc = (HttpsURLConnection) url.openConnection();
cert = hc.getServerCertificates()[0]; // ISE

// after
HttpsURLConnection hc = (HttpsURLConnection) url.openConnection();
hc.connect();
cert = hc.getServerCertificates()[0];
Defensive patterns

Strategy: validation

Validate before calling

if (conn.getResponseCode() > 0) { /* connected */ certificates = httpsConn.getServerCertificates(); }

Try / catch

try { certs = httpsConn.getServerCertificates(); } catch (IllegalStateException e) { httpsConn.connect(); certs = httpsConn.getServerCertificates(); }

Prevention

When it happens

Trigger: Calling ((HttpsURLConnection) conn).getServerCertificates() (or getCipherSuite, which also routes through handshake()) before connect()/getInputStream()/getResponseCode().

Common situations: Certificate-pinning or SSL-pinning checks run eagerly after openConnection(); security audits that inspect the handshake before making the actual request.

Related errors


AI-assisted analysis of didi/DoKit@626827cddb (2026-08-14). Data as JSON: /api/errors/4bfed0571ae8069f. Report an issue: GitHub.