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

  1. Call execute() before requesting the response body
  2. Use the high-level jsoup Connection API (Jsoup.connect(...).execute()) so ordering is enforced
  3. 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

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


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)