{"id":"ee0bae5c7c6c62a5","repo":"square/okhttp","slug":"unexpected-code-ee0bae","errorCode":null,"errorMessage":"Unexpected code ","messagePattern":"Unexpected code ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"samples/guide/src/main/java/okhttp3/recipes/CustomCipherSuites.java","lineNumber":161,"sourceCode":"\n    @Override public Socket createSocket(\n        InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {\n      return configureSocket((SSLSocket) delegate.createSocket(\n          address, port, localAddress, localPort));\n    }\n\n    protected SSLSocket configureSocket(SSLSocket socket) throws IOException {\n      return socket;\n    }\n  }\n\n  public void run() throws Exception {\n    Request request = new Request.Builder()\n        .url(\"https://publicobject.com/helloworld.txt\")\n        .build();\n\n    try (Response response = client.newCall(request).execute()) {\n      if (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response);\n\n      System.out.println(response.handshake().cipherSuite());\n      System.out.println(response.body().string());\n    }\n  }\n\n  public static void main(String... args) throws Exception {\n    new CustomCipherSuites().run();\n  }\n}\n","sourceCodeStart":143,"sourceCodeEnd":172,"githubUrl":"https://github.com/square/okhttp/blob/4fc083138014aba3d0078f5c26d1ce84815fa984/samples/guide/src/main/java/okhttp3/recipes/CustomCipherSuites.java#L143-L172","documentation":"Recipe-level guard after a GET over a client configured with a custom ConnectionSpec that restricts cipher suites to four ECDHE AEAD suites and a DelegatingSSLSocketFactory that forces those suites on each socket. Reaching this line means the TLS handshake negotiated one of the configured suites; if the HTTP response is then non-2xx, java.io.IOException(\"Unexpected code \" + response) is thrown. A cipher-suite negotiation FAILURE surfaces earlier as SSLHandshakeException, not here.","triggerScenarios":"GET https://publicobject.com/helloworld.txt through the customised client. Reaches this line on a non-2xx after a successful handshake; surfaces when the server lacks overlap with the four configured suites (but that throws earlier), or when the origin returns 4xx/5xx.","commonSituations":"Over-restricting cipher suites so older server stacks cannot negotiate (would surface as handshake failure, not this); assuming this exception is about ciphers when it is actually an HTTP error; server-side 5xx during maintenance.","solutions":["Inspect response.handshake().cipherSuite() — if it is one of the four configured, the handshake is fine and this is a plain HTTP error.","If you are getting SSLHandshakeException instead, broaden the ConnectionSpec or fall back to ConnectionSpec.MODERN_TLS.","Log response.code() to separate HTTP errors from cipher/TLS errors."],"exampleFix":"// before\ntry (Response response = client.newCall(request).execute()) {\n  if (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response);\n  ...\n}\n\n// after\ntry (Response response = client.newCall(request).execute()) {\n  if (!response.isSuccessful()) {\n    throw new IOException(\"HTTP \" + response.code()\n        + \" (negotiated cipher \" + response.handshake().cipherSuite() + \")\");\n  }\n  ...\n}","handlingStrategy":"try-catch","validationCode":"// Confirm the server supports at least one of your configured suites before relying on it\n// (e.g. with sslscan or openssl s_client -connect host:443 -cipher 'ECDHE-ECDSA-AES128-GCM-SHA256')\n// In code, broaden the spec as a fallback if negotiation fails.","typeGuard":null,"tryCatchPattern":"try {\n  Response response = client.newCall(request).execute();\n  if (!response.isSuccessful()) throw new HttpException(response.code(), response.message());\n} catch (SSLHandshakeException e) {\n  // No overlap between your 4 configured suites and the server\n  throw new TlsConfigException(\"Server supports none of the configured cipher suites\", e);\n} catch (IOException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Unexpected code\")) {\n    // handshake succeeded; this is a plain HTTP error\n  }\n  throw e;\n}","preventionTips":["Confirm cipher-suite overlap with the server (openssl s_client / sslscan) before restricting.","Log response.handshake().cipherSuite() to verify what was actually negotiated.","Keep ConnectionSpec.MODERN_TLS as a fallback when a custom spec fails.","Most apps should NOT customise cipher suites — the recipe warns about this."],"tags":["okhttp","http-status","cipher-suites","tls","java"],"analyzedSha":"4fc083138014aba3d0078f5c26d1ce84815fa984","analyzedAt":"2026-08-04T19:09:04.639Z","schemaVersion":2}