Retrofit - Too many follow-up requests: 21

52.1k Views Asked by At

I'm using retrofit to make requests.

I've got following error:

java.net.ProtocolException: Too many follow-up requests: 21

The code is like below:

private OkHttpClient httpClient;
private CookieManager cookieManager;

public <S> S createCookieService(Class<S> serviceClass) {
    httpClient.interceptors().clear();
    httpClient.setCookieHandler(cookieManager);
    Retrofit.Builder builder = new Retrofit
            .Builder()
            .client(httpClient)
            .baseUrl(url)
            .addConverterFactory(GsonConverterFactory.create());

    Retrofit retrofit = builder.client(httpClient).build();

    return retrofit.create(serviceClass);
}

And then I'm making requests:

example:

1) login

 @POST("/login")
 Call<User> login();

2) some request:

@GET("/request")
Call<PojoPojo> getPojo();

And I'm getting this error too many follow-up requests: 21.

Please help.

6

There are 6 best solutions below

1
On BEST ANSWER

Jake Wharton wrote:

This gets thrown (by OkHttp, not Retrofit) when there are more than 20 redirects when calling an endpoint. Usually this indicates a redirect cycle between two endpoints. Both Chrome and Firefox will also stop loading the request after this many redirects and fail the request.

You need to consult with your server team or endpoint documentation to ensure you are passing the correct data directly to the endpoint you want to call. No action for Retrofit to take here.

And rest of the thread is there: https://github.com/square/retrofit/issues/1561

0
On

As a workaround, it is possible to use:

new OkHttpClient.Builder()
    .followRedirects(false)
    .followSslRedirects(false)

Nice to take a look at okhttp3.internal.http.RetryAndFollowUpInterceptor class source code.

I'm using version 3.12.0 of OkHttp.

0
On

In my case it was happening because of the cookie in header was expired. It is clear that we need to fix this in server side code but in case we can't change server side code we can use this workaround.

Following is the workaround which worked for me

catch (ProtocolException e) {
        
        Timber.w(e);
        if (e.getMessage().contains("Too many follow-up requests")) {
            doSynchronousLogin();

            Request.Builder builder = chain.request().newBuilder();
            builder.addHeader("Cookie", dataManager.getCookie());
            Timber.w("Request processed after auto-login");
            return chain.proceed(builder.build());
        }
    }

Above code is added in a retrofit interceptor

0
On

For me the issue was: the request url was starting with "/".
Replace url @GET("/request") with @GET("request")

  • also the base url of the api should end with "/"
  • if using an Authorization header check if you need to set the value as "Bearer " + token instead

using retrofit 2.4.0 version:

<dependency>
    <groupId>com.squareup.retrofit2</groupId>
    <artifactId>retrofit</artifactId>
    <version>2.4.0</version>
</dependency>
0
On

In okHttpClient,in the interceptor if your using authenticator, remove that authenticator. It Sets the authenticator used to respond to challenges from origin servers. It Uses [proxyAuthenticator] to set the authenticator for proxy servers.

0
On

This also happen's when the token's header's key already exists and instead of replacing it with the new token as shown below:

response.request.newBuilder()
                .header("Authorization", token)
                .build()

you add the new token(a single key can have many values in the headers), what's common in a lot of questions is add the token like this:

response.request.newBuilder()
                .addHeader("Authorization", token)
                .build()

This will result the request failing again(401) and you'll end up in a loop.

TL;DR: The correct way of setting a new token is:

response.request.newBuilder()
                    .header("Authorization", token)
                    .build()