{"record":{"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/91a8b34c6f44bd28c421364f8edadc9f324dddd9/samples/guide/src/main/java/okhttp3/recipes/CustomCipherSuites.java#L143-L172","documentation":"Thrown in the custom-cipher-suites recipe after a successful TLS handshake: `if (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response)`. The custom ConnectionSpec restricts TLS to a handful of ECDHE cipher suites; if the server supports one of them the handshake succeeds and this line fires only on a non-2xx HTTP status. If none of the configured suites match, you get an SSLHandshakeException earlier, not this line.","triggerScenarios":"TLS handshake succeeded with one of the four configured suites against https://publicobject.com/helloworld.txt, but the server returned 404/403/5xx. (A cipher-suite mismatch would surface as SSLHandshakeException during connect, before any HTTP status exists.)","commonSituations":"Sample host removed the file; confusing a handshake failure (no common cipher) with this HTTP-status throw; restricting cipher suites so tightly that some servers cannot connect (but that is a different error).","solutions":["Distinguish TLS handshake errors from HTTP status errors; this line means TLS worked.","Inspect response.code() for the real HTTP status.","If you also see handshake errors elsewhere, widen the ConnectionSpec cipher list.","Branch on the code instead of throwing for clearer diagnostics."],"exampleFix":"// before\nif (!response.isSuccessful()) throw new IOException(\"Unexpected code \" + response);\n\n// after\nif (!response.isSuccessful()) {\n  throw new IOException(\"HTTP \" + response.code()\n      + \" (cipher=\" + response.handshake().cipherSuite() + \")\");\n}","handlingStrategy":"try-catch","validationCode":"// Confirm at least one configured cipher is server-supported before relying on this client.\n// (Best done by a smoke-test request; static checks of cipher names are fragile.)\ntry (Response r = client.newCall(smokeTestRequest).execute()) {\n  if (!r.isSuccessful()) { /* HTTP status; TLS worked */ }\n}","typeGuard":"static boolean handshakeUsedCustomSuite(Response r, List<CipherSuite> allowed) {\n  return r.handshake() != null && allowed.contains(r.handshake().cipherSuite());\n}","tryCatchPattern":"try {\n  // call\n} catch (SSLHandshakeException e) {\n  // no common cipher suite with the server -> widen ConnectionSpec\n} catch (IOException e) {\n  // includes 'Unexpected code' (HTTP status) once TLS succeeded\n}","preventionTips":["Distinguish SSLHandshakeException (cipher/TLS mismatch) from HTTP-status IOException.","Do not over-restrict cipher suites; most apps should leave defaults.","Inspect response.handshake().cipherSuite() to confirm negotiation.","Branch on code rather than throwing to keep HTTP errors visible."],"tags":["okhttp","http-status","cipher-suites","tls","java"],"backgroundTag":null,"analyzedSha":"91a8b34c6f44bd28c421364f8edadc9f324dddd9","analyzedAt":"2026-08-10T18:39:54.316Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}