Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OkHttpClient sometimes getting incomplete json response

I have been facing this incomplete json error and unable to find the issue. The API response work fine in POSTMAN. But this issue happened in my android emulator and it only happened randomly. This project is build with kotlin dagger-hilt retrofit2 okhttp3 gson.

Success Response

I/okhttp.OkHttpClient: <-- 200 OK http://10.0.2.2:8000/api/v1/user/friend/mutual?name=as (217ms)
I/okhttp.OkHttpClient: Host: 10.0.2.2:8000
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:38:59 GMT
I/okhttp.OkHttpClient: Connection: close
I/okhttp.OkHttpClient: X-Powered-By: PHP/7.4.13
I/okhttp.OkHttpClient: Cache-Control: no-cache, private
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:38:59 GMT
I/okhttp.OkHttpClient: Content-Type: application/json
I/okhttp.OkHttpClient: X-RateLimit-Limit: 60
I/okhttp.OkHttpClient: X-RateLimit-Remaining: 52
I/okhttp.OkHttpClient: Access-Control-Allow-Origin: *
I/okhttp.OkHttpClient: {"friends":[{"user_id":16,"name":"Grant Erdman","username":"lilla.kulas","email":"[email protected]","image":"https:\/\/via.placeholder.com\/640x480.png\/00dd44?text=dolor","relationship":"friend"}],"requests":[]}
I/okhttp.OkHttpClient: <-- END HTTP (217-byte body)

Incomplete Json Response missing "}"

I/okhttp.OkHttpClient: <-- 200 OK http://10.0.2.2:8000/api/v1/user/friend/mutual?name=as (198ms)
I/okhttp.OkHttpClient: Host: 10.0.2.2:8000
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:39:00 GMT
I/okhttp.OkHttpClient: Connection: close
I/okhttp.OkHttpClient: X-Powered-By: PHP/7.4.13
I/okhttp.OkHttpClient: Cache-Control: no-cache, private
I/okhttp.OkHttpClient: Date: Thu, 03 Mar 2022 06:39:00 GMT
I/okhttp.OkHttpClient: Content-Type: application/json
I/okhttp.OkHttpClient: X-RateLimit-Limit: 60
I/okhttp.OkHttpClient: X-RateLimit-Remaining: 51
I/okhttp.OkHttpClient: Access-Control-Allow-Origin: *
I/okhttp.OkHttpClient: {"friends":[{"user_id":16,"name":"Grant Erdman","username":"lilla.kulas","email":"[email protected]","image":"https:\/\/via.placeholder.com\/640x480.png\/00dd44?text=dolor","relationship":"friend"}],"requests":[]
I/okhttp.OkHttpClient: <-- END HTTP (216-byte body)
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.findplan, PID: 4695
    java.io.EOFException: End of input at line 1 column 217 path $.requests
        at com.google.gson.stream.JsonReader.nextNonWhitespace(JsonReader.java:1395)
        at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:481)
        at com.google.gson.stream.JsonReader.hasNext(JsonReader.java:413)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:216)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:40)
        at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27)
        at com.example.findplan.utils.NullOnEmptyConverterFactory$1.convert(NullOnEmptyConverterFactory.java:20)
        at com.example.findplan.utils.NullOnEmptyConverterFactory$1.convert(NullOnEmptyConverterFactory.java:16)
        at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:243)
        at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:153)
        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)
I/Process: Sending signal. PID: 4695 SIG: 9

My NetworkModule

@Singleton
    @Provides
    fun provideOkHttpClient(mySharedPreferences: MySharedPreferences): OkHttpClient {
        val builder = OkHttpClient
            .Builder()
            .connectTimeout(1, TimeUnit.MINUTES)
            .readTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(15, TimeUnit.SECONDS)
        val authenticationInterceptor = AuthenticationInterceptor(mySharedPreferences)
        builder.addInterceptor(authenticationInterceptor)
        val interceptor = HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
        builder.addNetworkInterceptor(interceptor)

        return builder.build()
    }

    @Singleton
    @Provides
    fun provideGson(): Gson {
        return GsonBuilder()
            .setLenient()
            .create()
    }

    @Singleton
    @Provides
    fun provideRetrofit(gson: Gson, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
            .baseUrl(BuildConfig.BASE_URL)
            .client(okHttpClient)
            .addConverterFactory(NullOnEmptyConverterFactory())
            .addConverterFactory(GsonConverterFactory.create(gson))
            .build()
    }

NullOnEmptyConverterFactory

public class NullOnEmptyConverterFactory extends Converter.Factory {

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        final Converter<ResponseBody, ?> delegate = retrofit.nextResponseBodyConverter(this, type, annotations);
        return new Converter<ResponseBody, Object>() {
            @Override
            public Object convert(ResponseBody body) throws IOException {
                if (body.contentLength() == 0) return null;
                return delegate.convert(body);
            }
        };
    }
}
like image 249
noahark Avatar asked Oct 15 '25 06:10

noahark


1 Answers

I suspect the Android emulator might be interfering with you here. I’ve seen issues with it misbehaving, particularly on Windows.

https://issuetracker.google.com/issues/119027639

If you'd like to workaround, consider changing your server to use something other than Connection: close to terminate your response body. Perhaps chunked encoding or a content-length header.

like image 138
Jesse Wilson Avatar answered Oct 17 '25 19:10

Jesse Wilson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!