jhy/jsoup · error · IllegalStateException
Not yet executed
Error message
Not yet executed
What it means
UrlConnectionExecutor.responseBody() requires that execute() has already been called and produced a live HttpURLConnection. If the internal conn reference is still null, the executor is in an invalid state and an IllegalStateException is thrown instead of attempting IO.
Solutions
- Call execute() before requesting the response body
- Use the high-level jsoup Connection API (Jsoup.connect(...).execute()) so ordering is enforced
- Create a fresh executor per request instead of reusing a closed one
Example fix
// before Connection.Response res = executor.responseBody(); // conn == null // after executor.execute(); InputStream body = executor.responseBody();
Defensive patterns
Strategy: type-guard
Validate before calling
if (executor == null || !executor.hasExecuted()) { // track via execute() return/flag
throw new IllegalStateException("Must call execute() before reading the body");
} Try / catch
try {
InputStream body = executor.responseBody();
} catch (IllegalStateException e) {
executor.execute(); // recover by completing the lifecycle
body = executor.responseBody();
} Prevention
- Always call execute() before responseBody(); prefer the high-level Connection API which enforces ordering
- Treat the executor as single-use; create a new one per request
- Do not read the body after safeClose()
When it happens
Trigger: Calling responseBody() directly on a newly constructed UrlConnectionExecutor without invoking execute() first; calling it after safeClose() reset the connection; reusing a single executor for a second response read after it was torn down.
Common situations: Custom request pipelines that bypass the normal jsoup Connection API and read the body out of order; code refactors where execute() moved behind a conditional branch that silently skipped it.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- You must execute the request before getting a response.
- URL not set. Make sure to call #url(...) before executing…
- Cannot follow redirect with a streamed request body…
- HTTP error fetching URL
- Unhandled content type. Must be a text or XML media type
AI-assisted analysis of jhy/jsoup@9851ac5d9c (2026-09-08).
Data as JSON: /api/errors/4bc78a6839f69a8e.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/jsoup/helper/UrlConnectionExecutor.java:66
res.url = conn.getURL();
res.statusCode = conn.getResponseCode();
res.statusMessage = conn.getResponseMessage();
if (res.statusMessage == null) res.statusMessage = ""; // getResponseMessage may be null but statusMessage() is not null
res.contentType = conn.getContentType();
res.contentLength = conn.getContentLength();
Map<String, List<String>> resHeaders = createHeaderMap(conn);
res.prepareResponse(resHeaders, prevRes);
return res;
} catch (IOException e) {
safeClose();
throw e;
}
}
@Override
InputStream responseBody() throws IOException {
if (conn == null) throw new IllegalStateException("Not yet executed");
return conn.getErrorStream() != null ? conn.getErrorStream() : conn.getInputStream();
}
@Override
void safeClose() {
if (conn != null) {
conn.disconnect();
conn = null;
}
}
// set up connection defaults, and details from request
private static HttpURLConnection createConnection(HttpConnection.Request req) throws IOException {
Proxy proxy = req.proxy();
final HttpURLConnection conn = (HttpURLConnection) (
proxy == null ?
req.url().openConnection() :
req.url().openConnection(proxy)View on GitHub (pinned to 9851ac5d9c)