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
- 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.
- Inspect response.code() and response.headers() before throwing — at minimum log Server, Content-Type, and the body.
- If behind a proxy, configure OkHttpClient with a Proxy and Authenticator (proxy auth) so the 407 turns into a 200.
- 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
- Point samples at a stable, owned endpoint rather than publicobject.com.
- Configure OkHttpClient.connectTimeout/readTimeout so unreachable hosts fail fast instead of hanging.
- If behind a corporate proxy, set Proxy and proxyAuthenticator.
- Always read the response body in catch via peekBody for diagnostics before closing.
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.