SonarSource/sonarqube · error · IllegalStateException

Fail to read response of

Error message

Fail to read response of %s

What it means

OkHttpResponse.content() reads the full response body of a SonarQube WS client response as a String. If reading the OkHttp ResponseBody throws an IOException, it is wrapped in an IllegalStateException with 'Fail to read response of <requestUrl>'. This means the HTTP request succeeded but the body could not be read (stream closed, connection dropped mid-body).

Solutions

  1. Read content() promptly, exactly once, while the response is open (don't cache the response across calls).
  2. Retry the whole request — this failure is usually transient.
  3. Increase OkHttp client read timeouts and enable keep-alive/retry-on-connection-failure.
  4. Inspect the cause IllegalStateException's IOException for reset vs timeout; check proxy/LB idle timeout settings.

Example fix

// before: body consumed after response closed
String body;
try (Response r = call.execute()) {
  bodyFuture.complete(r); // response closed here
}
String content = r.content(); // IllegalStateException

// after: read while open, retry on failure
try (Response r = call.execute()) {
  String content = r.content();
}
Defensive patterns

Strategy: retry

Validate before calling

// Ensure the response is ok and body present before reading:
if (!response.isSuccessful() || response.contentLength() == -1) { /* handle error path before content() */ }

Try / catch

try {
  String body = wsResponse.content();
} catch (IllegalStateException e) {
  if (e.getCause() instanceof IOException) {
    logger.warn("Body read failed for {} — retrying request", e.getMessage());
    body = retry(2, backoff(), wsClient::reissueAndRead);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling content() on a response whose underlying connection was closed/reset before or during body read; consuming the body after the response/connection was already closed or timed out; server aborting the response mid-transfer.

Common situations: Long responses over unstable connections; reading the body twice or after try-with-resources closed the response; server/proxy timeouts cutting large payloads; load balancers resetting idle connections.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of SonarSource/sonarqube@184c821202 (2026-09-09). Data as JSON: /api/errors/a5851e4fb41f7047. Report an issue: GitHub.

Appendix: source

Thrown at sonar-ws/src/main/java/org/sonarqube/ws/client/OkHttpResponse.java:90

  /**
   * Get stream of characters, decoded with the charset
   * of the Content-Type header. If that header is either absent or lacks a
   * charset, this will attempt to decode the response body as UTF-8.
   */
  @Override
  public Reader contentReader() {
    return okResponse.body().charStream();
  }

  /**
   * Get body content as a String. This response will be automatically closed.
   */
  @Override
  public String content() {
    try (ResponseBody body = okResponse.body()) {
      return body.string();
    } catch (IOException e) {
      throw fail(e);
    }
  }

  private RuntimeException fail(Exception e) {
    throw new IllegalStateException("Fail to read response of " + requestUrl(), e);
  }

  /**
   * Equivalent to closing contentReader or contentStream.
   */
  @Override
  public void close() {
    okResponse.close();
  }
}

View on GitHub (pinned to 184c821202)