jhy/jsoup · error · IOException
Cannot follow redirect with a streamed request body…
Error message
Cannot follow redirect with a streamed request body; disable followRedirects and resend with a fresh stream
What it means
When followRedirects is enabled and a redirect arrives, jsoup cannot replay a request whose body is a live InputStream (or a multipart upload), since the stream has already been consumed. It throws IOException telling you to disable redirects and send the body again yourself with a fresh stream.
Solutions
- Disable redirects: request.followRedirects(false), catch the redirect response, then resend manually with a fresh InputStream
- Buffer the body as a byte[] (requestBody(byte[]) or requestBody(String)) so it can be replayed across redirects
- If the redirect should change to GET (302/303), ensure the server responds with a method-changing status so the body is dropped
Example fix
// before
Connection.Response res = Jsoup.connect(url)
.requestBody(new FileInputStream(file))
.execute(); // throws on redirect
// after
Connection conn = Jsoup.connect(url)
.requestBody(new FileInputStream(file))
.followRedirects(false);
Connection.Response res = conn.execute();
if (res.statusCode() / 100 == 3) {
res = Jsoup.connect(res.header("Location"))
.requestBody(new FileInputStream(file)) // fresh stream
.execute();
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean risky = req.requestBody() instanceof InputStream || usesMultipart(req); if (risky && req.followRedirects()) { /* restructure: disable redirects */ } Try / catch
try { res = conn.execute(); } catch (IOException e) { if (e.getMessage().contains("streamed request body")) { /* resend manually with fresh stream */ } } Prevention
- Disable followRedirects for upload/stream-body requests
- Prefer byte[]/String bodies for POSTs that may be redirected
- Write upload helpers that detect 3xx and replay with a fresh InputStream
When it happens
Trigger: Executing a POST/PUT whose body was set via requestBody(InputStream) or via data requiring multipart, with followRedirects(true) (the default), and the server replies 301/302/307/308 keeping the same method.
Common situations: File-upload endpoints behind redirects; APIs moved to new hosts returning 307; retry logic resuming an upload session where the first request redirects.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- You must execute the request before getting a response.
- URL not set. Make sure to call #url(...) before executing…
- HTTP error fetching URL
- Unhandled content type. Must be a text or XML media type
- Too many redirects occurred trying to load URL
AI-assisted analysis of jhy/jsoup@9851ac5d9c (2026-09-08).
Data as JSON: /api/errors/dc9d5cf5824c9eb3.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/jsoup/helper/HttpConnection.java:931
if (!supportsBody)
Validate.isFalse(hasBody, "Cannot set a request body for HTTP method " + req.method());
// set up the request for execution
if (!req.data().isEmpty() && (!supportsBody || hasBody))
serialiseRequestUrl(req);
else if (supportsBody)
setOutputContentType(req);
long startTime = System.nanoTime();
RequestExecutor executor = RequestDispatch.get(req, prevRes);
Response res = null;
try {
res = executor.execute();
Method nextMethod = redirectMethod(res.statusCode, req.method());
if (nextMethod != null && res.hasHeader(LOCATION) && req.followRedirects()) {
if (nextMethod == req.method() && (req.body instanceof InputStream || needsMultipart(req)))
throw new IOException("Cannot follow redirect with a streamed request body; disable followRedirects and resend with a fresh stream");
if (nextMethod != req.method()) {
req.method(nextMethod);
req.data().clear();
req.requestBody(null);
for (String header : REDIRECT_CONTENT_HEADERS)
req.removeHeader(header);
}
String location = res.header(LOCATION);
Validate.notNull(location);
URL redir = StringUtil.resolve(req.url(), location);
if (!sameOrigin(req.url(), redir)) {
// remove sensitive headers; defense-in-depth against open redirects
req.removeHeader("Authorization");
req.removeHeader("Cookie");
req.removeHeader("Cookie2");
req.cookies().clear();View on GitHub (pinned to 9851ac5d9c)