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

  1. Register your own Imgur application at https://api.imgur.com/oauth2 and use your own Client-ID.
  2. Inspect response.code() and the JSON error body (Imgur returns {data:{error:...}, success:false}) — read response.body().string() in the error branch.
  3. Confirm the image file exists at an absolute path before posting.
  4. 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

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.