java – OKHttp throwing an illegal state exception when I try to log the network response-ThrowExceptions

Exception or error:

I put the following interceptor on my OkHttp client:

httpClient.addInterceptor(new Interceptor() {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        Log.d("Response", response.body().string());
        return response;
    }
    });

However, this isn’t playing nice with Retrofit 2. It seems that you can only read the stream from the response once and that might be what is causing the exception. I’m thinking retrofit is trying to parse the stream which the log already parsed. How then do I get my hands on the response? I’m currently trying to debug a very nasty and strange malformed json exception.

This is the exception stack trace:

07 - 28 10: 58: 21.575 22401 - 22529 / REDACTED E / AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
    Process: REDACTED, PID: 22401
    java.lang.IllegalStateException: closed
    at okhttp3.internal.http.Http1xStream$FixedLengthSource.read(Http1xStream.java: 378)
    at okio.Buffer.writeAll(Buffer.java: 956)
    at okio.RealBufferedSource.readByteArray(RealBufferedSource.java: 92)
    at okhttp3.ResponseBody.bytes(ResponseBody.java: 83)
    at okhttp3.ResponseBody.string(ResponseBody.java: 109)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.java: 90)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.java: 89)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.java: 89)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
    at REDACTED.ServiceGenerator$2.intercept(ServiceGenerator.java: 89)
    at okhttp3.RealCall$ApplicationInterceptorChain.proceed(RealCall.java: 187)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java: 160)
    at okhttp3.RealCall.access$100(RealCall.java: 30)
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java: 127)
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java: 32)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java: 1112)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java: 587)
    at java.lang.Thread.run(Thread.java: 841)

I see that there are multiple interceptors in the stack but I only ever explicitly add the one, which is the on that is throwing the exception.

How to solve:

You are consuming the response body in the interceptor, so you’re going to want to create a new response:

@Override public Response intercept(Chain chain) throws IOException {
  Response response = chain.proceed(chain.request());
  ResponseBody body = response.body();
  String bodyString = body.string();
  MediaType contentType = body.contentType();
  Log.d("Response", bodyString);
  return response.newBuilder().body(ResponseBody.create(contentType, bodyString)).build();
}

You may also want to check out the logging interceptor in OkHttp’s repo: https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor

###

Do not call response body more than once, since it is read as a stream and not stored in memory.

Maybe you are calling response.body().string() more than once because response body can be huge so OkHttp doesn’t store it in memory, it reads it as a stream from network when you need it.

When you read body as a string() OkHttp downloads response body and returns it to you without keeping reference to the string, it can’t be downloaded twice without new request.

https://github.com/square/okhttp/issues/1240

###


I also got this exception due to trying to convert response body 2X.
First i logged the response.body().string() & then again i passed the same to a method.
Which was causing the exception.
Check if the response body is converted to string more than once.

###

The error is weird but the the first problem I see is that you are using OKHTTP3 and trying to add a builder to the already created client.

The OkHttpClient is immutable now and you will have to add the interceptors directly to the OkHttpClient.Builder by calling addInterceptor method on the builder.

For more clarity on how to do this see this Github Issue. I think this should solve your problem.

###

Response body can be huge so OkHttp doesn’t store it in memory, it reads it as a stream from network when you need it.

When you read body as a string() OkHttp downloads response body and returns it to you without keeping reference to the string, it can’t be downloaded twice without new request.

###

I have this error when try to upload file (image) and use Chrome DevTools (Stetho).

Turning off Chrome DevTools solve my problem

Leave a Reply

Your email address will not be published. Required fields are marked *