Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
maboueita opened this issue Dec 26, 2014 · 31 comments

Comments

@maboueita
Copy link

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.

@swankjesse
Copy link
Collaborator

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

@maboueita
Copy link
Author

That was probably the case.

@GavinDon
Copy link

You can only call string() once. true

@fattoliu
Copy link

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

@artem-zinnatullin
Copy link
Contributor

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 [email protected]

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,
#1240 (comment)
, or
https://github.com/notifications/unsubscribe-auth/AA7B3EORk4IpQyujb1gMCpIcFpT2uJkWks5qXOMogaJpZM4DMQVK
.

#1240 (comment)

@GavinDon
Copy link

once requst once download

@Cai-Go
Copy link

Cai-Go commented Jul 22, 2016

response.body.string should be defined as a variable.but in fact ,i also don't why this.

@n-belokopytov
Copy link

Pffft. At least give people the option to do that if they want! Exceptions don't help much.

@fattoliu
Copy link

@artem-zinnatullin thanks very much!

@aliillyas
Copy link

aliillyas commented Apr 4, 2017

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

@choudhury-abhishek29
Copy link

Thanks a lot....solved a huge problem for me 👍

@eywalink
Copy link

eywalink commented Sep 13, 2017

if you have used response.body().string() once then you can new one same response and return in case that you will use "response.body().string()" again. It won't throw any exception if you do this.

@rozhok
Copy link

rozhok commented Sep 13, 2017

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

@swankjesse
Copy link
Collaborator

Which Javadocs did you read? That’s where we should add such a note.

@JakeWharton
Copy link
Collaborator

JakeWharton commented Sep 13, 2017 via email

@rozhok
Copy link

rozhok commented Sep 13, 2017

I've read javadocs for string() method in ResponseBody:

  /**
   * Returns the response as a string 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.
   */

Maybe my version is a bit outdated? 2.7.5

@KaNcHeR
Copy link

KaNcHeR commented Sep 20, 2017

Try the following:

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

it works for me

@MarcinMoskala
Copy link

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

@quanglth
Copy link

quanglth commented Mar 9, 2018

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.

facebook-github-bot pushed a commit to facebook/react-native that referenced this issue May 3, 2018
…g() twice

Summary:
Fixing from call response.body.string() twice in DevServerHelper.java.
square/okhttp#1240 (comment)

I'm getting error like this
```
05-01 21:16:47.080 22836-23064/com.my.company.bundle E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
                                                                               Process: com.my.company.bundle, PID: 22836
                                                                               java.lang.IllegalStateException: closed
                                                                                   at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:398)
                                                                                   at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:392)
                                                                                   at okhttp3.internal.c.a(Util.java:449)
                                                                                   at okhttp3.v.string(ResponseBody.java:174)
                                                                                   at com.facebook.react.devsupport.f$8.onResponse(DevServerHelper.java:487)
                                                                                   at com.newrelic.agent.android.instrumentation.okhttp3.CallbackExtension.onResponse(CallbackExtension.java:41)
                                                                                   at okhttp3.s$a.c(RealCall.java:153)
                                                                                   at okhttp3.internal.b.run(NamedRunnable.java:32)
                                                                                   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
                                                                                   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
                                                                                   at java.lang.Thread.run(Thread.java:764)
```

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

- In my case, My device is using a Proxy, and tried to connect the packager. When it failed from connecting packager through websocket, It crash by this line of code.
<!--
  Required: Write your test plan here. If you changed any code, please provide us with
  clear instructions on how you verified your changes work. Bonus points for screenshots and videos!
-->

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[ANDROID] [BUGFIX] [DevServerHelper] - fixing from calling body.string() twice.

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Closes #19088

Differential Revision: D7853822

Pulled By: mdvacca

fbshipit-source-id: c11a73ce2fa6d40b0a7bd8bc0fca7b07c6bc27ed
@AiFreeWay
Copy link

Check own okhttp interceptor's, throuble may be inside.

@gelbertgel
Copy link

gelbertgel commented Jun 6, 2018

       @Override
        public void onResponse(@NonNull Call call, @NonNull Response response) {
            if (response.isSuccessful()) {

                try {

                    final String url = response.request().url().toString();
                    Log.i(TAG, " url: " + url);

                    Thread diffThread = new Thread(new Runnable() {
                    @Override
                     public void run() {

                            try {

                                System.setProperty("http.keepAlive", "false");

                                ResponseBody responseBody = response.body();

                                if (responseBody == null) {
                                    return;
                                }

                                String source = responseBody.string();
                                } catch(Exception e){
                                  ---> Exception! message:closed
                                }
  }

How can I do that? It gives an error if it is in a different thread ?

macdoum1 pushed a commit to macdoum1/react-native that referenced this issue Jun 28, 2018
…g() twice

Summary:
Fixing from call response.body.string() twice in DevServerHelper.java.
square/okhttp#1240 (comment)

I'm getting error like this
```
05-01 21:16:47.080 22836-23064/com.my.company.bundle E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
                                                                               Process: com.my.company.bundle, PID: 22836
                                                                               java.lang.IllegalStateException: closed
                                                                                   at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:398)
                                                                                   at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:392)
                                                                                   at okhttp3.internal.c.a(Util.java:449)
                                                                                   at okhttp3.v.string(ResponseBody.java:174)
                                                                                   at com.facebook.react.devsupport.f$8.onResponse(DevServerHelper.java:487)
                                                                                   at com.newrelic.agent.android.instrumentation.okhttp3.CallbackExtension.onResponse(CallbackExtension.java:41)
                                                                                   at okhttp3.s$a.c(RealCall.java:153)
                                                                                   at okhttp3.internal.b.run(NamedRunnable.java:32)
                                                                                   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
                                                                                   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
                                                                                   at java.lang.Thread.run(Thread.java:764)
```

<!--
  Required: Write your motivation here.
  If this PR fixes an issue, type "Fixes #issueNumber" to automatically close the issue when the PR is merged.
-->

- In my case, My device is using a Proxy, and tried to connect the packager. When it failed from connecting packager through websocket, It crash by this line of code.
<!--
  Required: Write your test plan here. If you changed any code, please provide us with
  clear instructions on how you verified your changes work. Bonus points for screenshots and videos!
-->

<!--
  Does this PR require a documentation change?
  Create a PR at https://github.com/facebook/react-native-website and add a link to it here.
-->

<!--
  Required.
  Help reviewers and the release process by writing your own release notes. See below for an example.
-->

[ANDROID] [BUGFIX] [DevServerHelper] - fixing from calling body.string() twice.

<!--
  **INTERNAL and MINOR tagged notes will not be included in the next version's final release notes.**

    CATEGORY
  [----------]      TYPE
  [ CLI      ] [-------------]    LOCATION
  [ DOCS     ] [ BREAKING    ] [-------------]
  [ GENERAL  ] [ BUGFIX      ] [ {Component} ]
  [ INTERNAL ] [ ENHANCEMENT ] [ {Filename}  ]
  [ IOS      ] [ FEATURE     ] [ {Directory} ]   |-----------|
  [ ANDROID  ] [ MINOR       ] [ {Framework} ] - | {Message} |
  [----------] [-------------] [-------------]   |-----------|

 EXAMPLES:

 [IOS] [BREAKING] [FlatList] - Change a thing that breaks other things
 [ANDROID] [BUGFIX] [TextInput] - Did a thing to TextInput
 [CLI] [FEATURE] [local-cli/info/info.js] - CLI easier to do things with
 [DOCS] [BUGFIX] [GettingStarted.md] - Accidentally a thing/word
 [GENERAL] [ENHANCEMENT] [Yoga] - Added new yoga thing/position
 [INTERNAL] [FEATURE] [./scripts] - Added thing to script that nobody will see
-->
Closes facebook#19088

Differential Revision: D7853822

Pulled By: mdvacca

fbshipit-source-id: c11a73ce2fa6d40b0a7bd8bc0fca7b07c6bc27ed
@wnchen
Copy link

wnchen commented Jul 20, 2018

Response body is not stored in memory. .string() reads as stream from network. That is it.

@sumanpula
Copy link

sumanpula commented Aug 25, 2019

Try storing response in string variable separately like this,

String res = response.body().string();

Then use variable res.

@yaitskov
Copy link

how come. it is not working

@Dreamerpro
Copy link

For me the problem was the wrapper function that returned Response object. Like this

callAPI(...){
.....
client.newCall(request).execute().also { 
        return it
    }
...

@ramchhabra
Copy link

I tried something like this

Response response = chain.proceed(newRequest);
Response responseTmp = chain.proceed(newRequest);

responseTmp.body().string();

and it works

@JakeWharton
Copy link
Collaborator

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

@ernest-kiwele
Copy link

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)

@mrHesham
Copy link

mrHesham commented Oct 26, 2020

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);	
                        }
                    });
             
            }

@mvrueden
Copy link

I encountered the same issue, receiving an Exception when reading the response, e.g. responseBody.string().
However in my code I only use it once.
BUT: When debugging, I added (by accident) a watch expression to responseBody.string() which then caused the actual execution to fail.

@arsalanImtiaz455
Copy link

Try the following:

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

it works for me

why each api gets called twice ?
I am stuck with this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests