okhttp: java.lang.IllegalStateException: closed when trying to access response in onResponse(Response response)

I get

java.lang.IllegalStateException: closed
            at com.squareup.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:455)
            at okio.Buffer.writeAll(Buffer.java:594)
            at okio.RealBufferedSource.readByteArray(RealBufferedSource.java:87)
            at com.squareup.okhttp.ResponseBody.bytes(ResponseBody.java:56)
            at com.squareup.okhttp.ResponseBody.string(ResponseBody.java:82)

when trying to access the response body using:

response.body().string();

inside onResponse(Response response) callback.

About this issue

  • Original URL
  • State: closed
  • Created 10 years ago
  • Reactions: 37
  • Comments: 31 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Are you reading the response body 2x? You can only call string() once.

Try the following:

ResponseBody responseBodyCopy = response.peekBody(Long.MAX_VALUE);
responseBodyCopy.string();

it works for me

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.

On Tue, Jul 19, 2016 at 5:46 PM fattolium

< mailto:fattolium notifications@github.com

wrote:

You can call string() once. But I don’t know why

You are receiving this because you are subscribed to this thread.

Reply to this email directly, https://github.com/square/okhttp/issues/1240#issuecomment-233655904 , or https://github.com/notifications/unsubscribe-auth/AA7B3EORk4IpQyujb1gMCpIcFpT2uJkWks5qXOMogaJpZM4DMQVK .

https://github.com/square/okhttp/issues/1240#issuecomment-233655904

Beware if you have response.body().string() in your watch list that will cause your code to fail. Since watch list will run automatically.

Don’t try to use response.body.string() directly. Just using like below: ResponseBody responseBody = response.body(); String content = responseBody.string(); // Do something with "content" variable

Reason: The the string of body is stored in memory to variable content, so we don’t need to care of whether the state is closed.

It’s documented on ResponseBody.

On Wed, Sep 13, 2017 at 11:04 AM Włodzimierz Rożkow < notifications@github.com> wrote:

At least it would be nice to add explanation to javadocs about this. I just broke my production because of twice call to string()

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/square/okhttp/issues/1240#issuecomment-329197139, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEEEZm2BB9oiE_q1GHhuSJ8E3vD_JiRks5sh-72gaJpZM4DMQVK .

You can only call string() once. true

You can call string() once. But I don’t know why

Adding this bit as it may help someone else. I was puzzled to encounter the very same exception while calling ResponseBody.string() only once.

The problem, I realized later, was due to the execution context of my request: using a try with resources block with the response causes the same problem when the response body is read outside of the try block:

try (Response response = client.newCall(request.build()).execute()) {
	return response;
} //response.close() called implicitly by the JVM

If response is processed outside this method, the IllegalStateException is equally thrown. That’s because the try with resources block will call response.close(). An easy workaround for such a design is to read the body in the try block itself and return it (or both it and the response object in a different data structure)

@KaNcHeR It looks like a dirty hack, but it works 😄 Thanks a lot

Thanks a lot…solved a huge problem for me 👍

just call response.close();

example :

@Override public void onResponse(Call call, Response response) throws IOException {

                    final int code  = response.code();
                    final String body = response.body().string();
                    response.close();

                    Login.this.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
	                //do any thing with body variable 
			Print(body);	
                        }
                    });
             
            }

That makes two HTTP requests. You don’t want to do that.