{"record":{"id":"4bfed0571ae8069f","repo":"didi/DoKit","slug":"connection-has-not-yet-been-established","errorCode":null,"errorMessage":"Connection has not yet been established","messagePattern":"Connection has not yet been established","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java","lineNumber":1291,"sourceCode":"        }\n    }\n\n    static final class OkHttpsURLConnection extends DelegatingHttpsURLConnection {\n        private final OkHttpURLConnection delegate;\n\n        OkHttpsURLConnection(URL url, OkHttpClient client) {\n            this(new OkHttpURLConnection(url, client));\n        }\n\n        OkHttpsURLConnection(OkHttpURLConnection delegate) {\n            super(delegate);\n            this.delegate = delegate;\n        }\n\n        @Override\n        protected Handshake handshake() {\n            if (delegate.call == null) {\n                throw new IllegalStateException(\"Connection has not yet been established\");\n            }\n\n            return delegate.handshake;\n        }\n\n        @Override\n        public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {\n            delegate.client = delegate.client.newBuilder()\n                    .hostnameVerifier(hostnameVerifier)\n                    .build();\n        }\n\n        @Override\n        public HostnameVerifier getHostnameVerifier() {\n            return delegate.client.hostnameVerifier();\n        }\n\n        @Override","sourceCodeStart":1273,"sourceCodeEnd":1309,"githubUrl":"https://github.com/didi/DoKit/blob/626827cddb2feb2f3aee87a52a064b4e5ca2bed4/Android/dokit/src/main/java/com/didichuxing/doraemonkit/aop/urlconnection/ObsoleteUrlFactory.java#L1273-L1309","documentation":"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.","triggerScenarios":"Calling ((HttpsURLConnection) conn).getServerCertificates() (or getCipherSuite, which also routes through handshake()) before connect()/getInputStream()/getResponseCode().","commonSituations":"Certificate-pinning or SSL-pinning checks run eagerly after openConnection(); security audits that inspect the handshake before making the actual request.","solutions":["Trigger the connection first (connect() or getResponseCode()), then read the handshake.","For pinning, prefer OkHttp's CertificatePinner configured on the client rather than manual handshake inspection.","Restructure the check into a response interceptor or after getInputStream()."],"exampleFix":"// before\nHttpsURLConnection hc = (HttpsURLConnection) url.openConnection();\ncert = hc.getServerCertificates()[0]; // ISE\n\n// after\nHttpsURLConnection hc = (HttpsURLConnection) url.openConnection();\nhc.connect();\ncert = hc.getServerCertificates()[0];","handlingStrategy":"validation","validationCode":"if (conn.getResponseCode() > 0) { /* connected */ certificates = httpsConn.getServerCertificates(); }","typeGuard":null,"tryCatchPattern":"try { certs = httpsConn.getServerCertificates(); } catch (IllegalStateException e) { httpsConn.connect(); certs = httpsConn.getServerCertificates(); }","preventionTips":["Establish the connection before inspecting TLS state.","Prefer OkHttp CertificatePinner over manual handshake checks."],"tags":["network","https","tls","state-machine"],"backgroundTag":null,"analyzedSha":"626827cddb2feb2f3aee87a52a064b4e5ca2bed4","analyzedAt":"2026-08-14T12:45:58.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}