square/okhttp · error · IOException
Unexpected code
Error message
Unexpected code
What it means
Recipe-level guard after POSTing a streaming RequestBody (an anonymous subclass that writes generated markdown prime factorisations to the BufferedSink) to GitHub's markdown/raw endpoint. If the response is non-2xx, java.io.IOException("Unexpected code " + response) is thrown. The body is produced on-demand during writeTo(), so a writeTo() IOException (e.g. the connection is closed mid-upload) surfaces from execute(), not this line.
Source
Thrown at samples/guide/src/main/java/okhttp3/recipes/PostStreaming.java:61
}
}
private String factor(int n) {
for (int i = 2; i < n; i++) {
int x = n / i;
if (x * i == n) return factor(x) + " × " + i;
}
return Integer.toString(n);
}
};
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.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 PostStreaming().run();
}
}
View on GitHub (pinned to 4fc0831380)
Solutions
- Verify contentType() returns exactly text/x-markdown; charset=utf-8.
- Inspect response.code() and rate-limit headers.
- Authenticate to GitHub to lift the cap.
- Write a small, deterministic test payload first to isolate content vs. transport issues.
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("GitHub markdown/raw " + response.code()
+ " (contentType=" + MEDIA_TYPE_MARKDOWN + ")");
}
...
} Defensive patterns
Strategy: validation
Validate before calling
// Ensure the streaming body's content type matches what the endpoint expects
MediaType mediaType = MediaType.get("text/x-markdown; charset=utf-8");
// keep contentType() returning exactly this; authenticate the request:
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.header("Authorization", "Bearer " + token)
.header("User-Agent", "MyApp/1.0")
.post(streamingBody) // contentType() == mediaType
.build(); Try / catch
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
if (response.code() == 415) throw new UnsupportedMediaTypeException("Use text/x-markdown; charset=utf-8");
if (response.code() == 403) throw new RateLimitedException(response.header("X-RateLimit-Reset"));
throw new HttpException(response.code(), response.message());
}
} Prevention
- Make the anonymous RequestBody's contentType() return exactly the expected media type.
- Authenticate GitHub POSTs and respect rate limits.
- Keep writeTo() deterministic and UTF-8 clean to avoid pre-throw IOExceptions.
- Use a small fixed payload in tests to isolate content vs. transport errors.
When it happens
Trigger: POST https://api.github.com/markdown/raw with a chunked streaming body. Reaches this line when the body was sent successfully but GitHub returned 4xx/5xx: 403 (rate limit), 415 (media type mismatch — must be text/x-markdown), 404/410 (endpoint retired), 400 (malformed body).
Common situations: Wrong content-type in contentType() (must match the .header or the endpoint's expectation); GitHub rate limit on the unauthenticated markdown API; a writeTo() bug producing an invalid UTF-8 sequence (would throw earlier).
Related errors
AI-assisted analysis of square/okhttp@4fc0831380 (2026-08-04).
Data as JSON: /data/errors/5027c105b57a619a.json.
Report an issue: GitHub.