{"id":"86751ab560a219f0","repo":"square/okhttp","slug":"unexpected-code-86751a","errorCode":null,"errorMessage":"Unexpected code ","messagePattern":"Unexpected code ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"samples/guide/src/main/java/okhttp3/recipes/Authenticate.java","lineNumber":50,"sourceCode":"          }\n\n          System.out.println(\"Authenticating for response: \" + response);\n          System.out.println(\"Challenges: \" + response.challenges());\n          String credential = Credentials.basic(\"jesse\", \"password1\");\n          return response.request().newBuilder()\n              .header(\"Authorization\", credential)\n              .build();\n        })\n        .build();\n  }\n\n  public void run() throws Exception {\n    Request request = new Request.Builder()\n        .url(\"http://publicobject.com/secrets/hellosecret.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.body().string());\n    }\n  }\n\n  public static void main(String... args) throws Exception {\n    new Authenticate().run();\n  }\n}\n","sourceCodeStart":32,"sourceCodeEnd":60,"githubUrl":"https://github.com/square/okhttp/blob/4fc083138014aba3d0078f5c26d1ce84815fa984/samples/guide/src/main/java/okhttp3/recipes/Authenticate.java#L32-L60","documentation":"Recipe-level guard after an authenticated GET. The client is configured with an Authenticator that retries once with HTTP Basic credentials (Credentials.basic(\"jesse\",\"password1\")) on a 401. After the authenticator gives up (it returns null if an Authorization header is already present), the final Response reaches this line; if it is still non-2xx, java.io.IOException(\"Unexpected code \" + response) is thrown.","triggerScenarios":"GET http://publicobject.com/secrets/hellosecret.txt where the server demands auth. Thrown when the Basic credentials are wrong/expired (final response stays 401), when the authenticator returns null on the second 401, or when the protected resource genuinely returns 403/404 after authenticating. Note the URL uses http, so credentials are sent in cleartext after the redirect.","commonSituations":"Placeholder credentials 'jesse/password1' from the recipe were never valid for your target; server changed its auth scheme (Digest, OAuth, Bearer) so Basic is rejected; the resource was moved/deleted (404 after auth); using http:// so the credentials leak on the wire and the host redirects to https mid-flow.","solutions":["Confirm the credentials are actually correct for the realm — check response.challenges() (printed by the recipe) for the expected scheme/realm.","Inspect response.code() and the Authorization history via response.priorResponse() to see how many auth attempts occurred.","Match the Authenticator's scheme to what the server advertises (use Credentials.basic only for WWW-Authenticate: Basic).","Use https:// so credentials are encrypted.","If 404 after auth, the path is wrong — nothing to do with authentication."],"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.code() == 401) {\n    throw new IOException(\"Auth failed; challenges=\" + response.challenges()\n        + \" (check username/password and scheme)\");\n  }\n  if (!response.isSuccessful()) {\n    throw new IOException(\"HTTP \" + response.code() + \" for \" + response.request().url());\n  }\n  ...\n}","handlingStrategy":"validation","validationCode":"// Match the auth scheme the server actually advertises\ntry (Response probe = clientWithoutAuth.newCall(probeRequest).execute()) {\n  List<Challenge> challenges = probe.challenges(); // scheme + realm from WWW-Authenticate\n  if (challenges.isEmpty() || !\"basic\".equalsIgnoreCase(challenges.get(0).scheme())) {\n    throw new IllegalStateException(\"Server does not accept Basic auth: \" + challenges);\n  }\n}","typeGuard":null,"tryCatchPattern":"try (Response response = client.newCall(request).execute()) {\n  if (response.code() == 401) {\n    // Auth failed even after the Authenticator retried once\n    throw new AuthException(response.challenges());\n  }\n  if (!response.isSuccessful()) throw new HttpException(response.code(), response.message());\n  // use response\n}","preventionTips":["Confirm the credentials and realm before deploying.","Inspect response.challenges() to verify the scheme is Basic.","Use https:// so Basic credentials are encrypted.","Limit the Authenticator to one retry to avoid loops (the recipe returns null when Authorization is already set)."],"tags":["okhttp","http-status","authentication","basic-auth","java"],"analyzedSha":"4fc083138014aba3d0078f5c26d1ce84815fa984","analyzedAt":"2026-08-04T19:09:04.639Z","schemaVersion":2}