square/okhttp · error · IOException

Unexpected code

Error message

Unexpected code 

What it means

SynchronousGet.java:33 throws 'Unexpected code ' whenever the plain GET to https://publicobject.com/helloworld.txt returns a non-2xx status. This is the most minimal OkHttp recipe and the guard is intentionally pedagogical — it demonstrates the canonical 'check isSuccessful() before reading body' pattern. OkHttp itself never throws this; it is application code in the sample.

Source

Thrown at samples/guide/src/main/java/okhttp3/recipes/SynchronousGet.java:33

 */
package okhttp3.recipes;

import java.io.IOException;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public final class SynchronousGet {
  private final OkHttpClient client = new OkHttpClient();

  public void run() throws Exception {
    Request request = new Request.Builder()
        .url("https://publicobject.com/helloworld.txt")
        .build();

    try (Response response = client.newCall(request).execute()) {
      if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

      Headers responseHeaders = response.headers();
      for (int i = 0; i < responseHeaders.size(); i++) {
        System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
      }

      System.out.println(response.body().string());
    }
  }

  public static void main(String... args) throws Exception {
    new SynchronousGet().run();
  }
}

View on GitHub (pinned to 4fc0831380)

Solutions

  1. Check network connectivity and confirm the URL still resolves in a browser; switch the recipe to a stable endpoint (e.g. https://raw.githubusercontent.com/.../helloworld.txt) if publicobject.com is down.
  2. Inspect response.code() and response.headers() before throwing — at minimum log Server, Content-Type, and the body.
  3. If behind a proxy, configure OkHttpClient with a Proxy and Authenticator (proxy auth) so the 407 turns into a 200.
  4. Handle redirects explicitly via .followRedirects(true) (default) and check response.priorResponse() if a redirect chain lands on an error.

Example fix

// before
try (Response response = client.newCall(request).execute()) {
  if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
  ...
}

// after
try (Response response = client.newCall(request).execute()) {
  if (!response.isSuccessful()) {
    throw new IOException(request.url() + " -> " + response.code()
        + " " + response.header("Server"));
  }
  ...
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Cheap liveness probe before the real GET
Request head = new Request.Builder().url(url).head().build();
try (Response r = client.newCall(head).execute()) {
  if (!r.isSuccessful()) {
    throw new IllegalStateException(url + " not fetchable: " + r.code());
  }
}

Try / catch

try (Response response = client.newCall(request).execute()) {
  if (!response.isSuccessful()) {
    throw new IOException(request.url() + " -> " + response.code()
        + " " + response.header("Server"));
  }
  consume(response.body().string());
} catch (java.net.UnknownHostException | java.net.SocketTimeoutException e) {
  // network-level failure, distinct from a non-2xx response
  throw new IOException("cannot reach " + request.url(), e);
}

Prevention

When it happens

Trigger: The demo host publicobject.com is unavailable (502/503/504) or the path /helloworld.txt has been moved/deleted (404). A captive portal returning 302/200-HTML breaks the assertion conceptually but stays 'successful' on code; an upstream proxy returning 407 auth-required, or Cloudflare challenging with 403/503, trips the throw.

Common situations: Running the bare-bones sample offline or behind a corporate proxy; DNS resolution succeeding but the origin returning a maintenance page; certificate mismatch causing an earlier SSLPeerUnverifiedException (distinct error); hotlink protection returning 403.

Related errors


AI-assisted analysis of square/okhttp@4fc0831380 (2026-08-04). Data as JSON: /data/errors/500954d40d7dc143.json. Report an issue: GitHub.