square/okhttp · error · IOException
Unexpected code
Error message
Unexpected code
What it means
Recipe-level guard after POSTing a multipart image upload to Imgur with a Client-ID authorization header. If the response is non-2xx, java.io.IOException("Unexpected code " + response) is thrown. The most common real-world cause is Imgur rejecting the request (auth, quota, bad payload), since the recipe uses a shared demo client ID. If docs/images/logo-square.png is missing, the RequestBody.create(file, ...) call throws FileNotFoundException earlier, not here.
Source
Thrown at samples/guide/src/main/java/okhttp3/recipes/PostMultipart.java:55
public void run() throws Exception {
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "Square Logo")
.addFormDataPart("image", "logo-square.png",
RequestBody.create(
new File("docs/images/logo-square.png"),
MEDIA_TYPE_PNG))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
}
public static void main(String... args) throws Exception {
new PostMultipart().run();
}
}
View on GitHub (pinned to 4fc0831380)
Solutions
- Register your own Imgur application at https://api.imgur.com/oauth2 and use your own Client-ID.
- Inspect response.code() and the JSON error body (Imgur returns {data:{error:...}, success:false}) — read response.body().string() in the error branch.
- Confirm the image file exists at an absolute path before posting.
- Set an explicit MediaType and filename in addFormDataPart.
Example fix
// before
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
...
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
...
}
// after
.header("Authorization", "Client-ID " + MY_REGISTERED_CLIENT_ID)
...
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
String body = response.body().string();
throw new IOException("Imgur " + response.code() + ": " + body);
}
...
} Defensive patterns
Strategy: validation
Validate before calling
// Validate inputs and use your own registered Imgur Client-ID
File image = new File(context, "docs/images/logo-square.png");
if (!image.isFile()) throw new FileNotFoundException(image.getAbsolutePath());
String clientId = System.getenv("IMGUR_CLIENT_ID"); // your own key, not the demo one
if (clientId == null) throw new IllegalStateException("IMGUR_CLIENT_ID not set");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("image", image.getName(),
RequestBody.create(image, MediaType.get("image/png")))
.build();
Request request = new Request.Builder()
.url("https://api.imgur.com/3/image")
.header("Authorization", "Client-ID " + clientId)
.post(body).build(); Try / catch
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
String errBody = response.body().string();
if (response.code() == 401 || response.code() == 403)
throw new AuthException("Imgur Client-ID invalid/revoked: " + errBody);
if (response.code() == 429)
throw new RateLimitedException("Imgur cap reached: " + errBody);
throw new HttpException(response.code(), errBody);
}
} Prevention
- Register your own Imgur application and read the Client-ID from config/env.
- Read response.body().string() in the error branch — Imgur returns structured JSON errors.
- Confirm the image file exists at an absolute path.
- Watch the per-app daily upload cap.
When it happens
Trigger: POST https://api.imgur.com/3/image with MultipartBody.FORM containing title + image file, Authorization: Client-ID 9199fdef135c122. Fires on 401/403 (Client-ID revoked or rate-limited — Imgur caps demo keys), 400 (missing/invalid image bytes or wrong field name), 429 (per-app ratelimit), or 503.
Common situations: Using the shared demo Client-ID (9199fdef135c122) which has been throttled/revoked because everyone copies the recipe; the local image file path being wrong (→ earlier FileNotFoundException); Imgur API v3 rate limits (≈1,250/day for anonymous uploads); missing/invalid mime type on the part.
Related errors
AI-assisted analysis of square/okhttp@4fc0831380 (2026-08-04).
Data as JSON: /data/errors/aff6f51d4f6c3590.json.
Report an issue: GitHub.