Retrofit: java.lang.IllegalStateException: closed

Created on 18 Mar 2020  路  2Comments  路  Source: square/retrofit

I am using two kind of interceptor, one is HttpLoggingInterceptor and another one is my custom AuthorizationInterceptor

I am using below updated retrofit version library,

def retrofit_version = "2.7.2"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
implementation 'com.squareup.okhttp3:logging-interceptor:4.4.0'
implementation 'com.squareup.okhttp3:okhttp:4.4.0'

below is code

private fun makeOkHttpClient(): OkHttpClient {
        val logger = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
        return OkHttpClient.Builder()
            .addInterceptor(AuthorizationInterceptor(context)) <---- To put Authorization Barrier
            .addInterceptor(logger) <---- To log Http request and response
            .followRedirects(false)
            .connectTimeout(50, TimeUnit.SECONDS)
            .readTimeout(50, TimeUnit.SECONDS)
            .writeTimeout(50, TimeUnit.SECONDS)
            .build()
    }

When I try to execute below code, in file named SynchronizationManager.kt, it gives me an error.

var rulesResourcesServices = RetrofitInstance(context).buildService(RulesResourcesServices::class.java)
val response = rulesResourcesServices.getConfigFile(file).execute() <---In this line I am getting an exception... (which is at SynchronizationManager.kt:185)

My RulesResourcesServices class is here

After debug I found that when below function called, at that time I am getting an exception

@GET("users/me/configfile")
    fun getConfigFile(@Query("type") type: String): Call<ResponseBody>

I am getting following error

java.lang.IllegalStateException: closed
at okio.RealBufferedSource.read(RealBufferedSource.kt:184)
at okio.ForwardingSource.read(ForwardingSource.kt:29)
at retrofit2.OkHttpCall$ExceptionCatchingResponseBody$1.read(OkHttpCall.java:288)
at okio.RealBufferedSource.readAll(RealBufferedSource.kt:293)
at retrofit2.Utils.buffer(Utils.java:316)<------- ANDROID IS HIGH-LIGHTING
at retrofit2.BuiltInConverters$BufferingResponseBodyConverter.convert(BuiltInConverters.java:103)
at retrofit2.BuiltInConverters$BufferingResponseBodyConverter.convert(BuiltInConverters.java:96)
at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225)
at retrofit2.OkHttpCall.execute(OkHttpCall.java:188)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall.execute(DefaultCallAdapterFactory.java:97)
at android.onetap.SynchronizationManager.downloadFile(SynchronizationManager.kt:185)
at android.base.repository.LoginRepository.downloadConfigFilesAndLocalLogin(LoginRepository.kt:349)
at android.base.repository.LoginRepository.access$downloadConfigFilesAndLocalLogin(LoginRepository.kt:48)
at android.base.repository.LoginRepository$loginTask$2.onSRPLoginComplete(LoginRepository.kt:210)
at android.base.repository.LoginRepository$performSyncLogin$srpLogin$1$1.onSRPLogin(LoginRepository.kt:478)
at android.srp.SRPManager$SRPLoginOperation$execute$1.invokeSuspend(SRPManager.kt:323)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:561)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:727)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:667)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:655)

Below is screenshot, in that you can see that, I am getting output of file but don't know why it is throwing an exception.

enter image description here

checked Retrofit's Utils class

https://github.com/square/retrofit/blob/master/retrofit/src/main/java/retrofit2/Utils.java

static ResponseBody buffer(final ResponseBody body) throws IOException {
    Buffer buffer = new Buffer();
    body.source().readAll(buffer); <-This line throws an error.
    return ResponseBody.create(body.contentType(), body.contentLength(), buffer);
  }

Update

Same thing is working fine with enqueue method.

response.enqueue(object : Callback<ResponseBody?> {

override fun onResponse(call: Call<ResponseBody?>, response: retrofit2.Response<ResponseBody?>) { 
 }
})

Most helpful comment

Best guess is that you're reading and closing the response body in your interceptor which means it's not available to consume by the normal Retrofit internals. If you want to read the body in an interceptor and you don't plan on replacing it then it's best to use OkHttp's peekBody().

If it's not this, please isolate the behavior to a small executable sample or failing test so we can debug what's going on.

All 2 comments

Best guess is that you're reading and closing the response body in your interceptor which means it's not available to consume by the normal Retrofit internals. If you want to read the body in an interceptor and you don't plan on replacing it then it's best to use OkHttp's peekBody().

If it's not this, please isolate the behavior to a small executable sample or failing test so we can debug what's going on.

Hi @JakeWharton, issue is resolved. Thank you so much for your response, I have shared detail in StackOverflow, with your thanks, so it will be helpful for others.

Was this page helpful?
0 / 5 - 0 ratings