google-ads-java: Infinite loop if refresh token is invalid

Hi there,

If I use an invalid refresh token, it goes into an infinite loop, not throwing an exception. It keeps trying requesting itself again and again…

This is so frustrating as refresh token can be broken many reasons(Change password, etc) If there are some options which can raise an exception, it would be much more easy to handle these situations.

Please let me know your opinion or guide me!

  • Test Code
   @Test(expected = GoogleAdsException.class)
    public void infinite_loop_exception_test()  throws Exception{

        String personal_mcc_token = "1/SomeBrokenRefreshToken";
        String mcc_id = "xxxxxxx";
        String customer_client_id = "xxxxxxx";

        GoogleAdsClient googleAdsClient = testHelper.getGoogleClient(mcc_id,  personal_mcc_token);
        GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient();
        SearchGoogleAdsRequest request = SearchGoogleAdsRequest.newBuilder()
                .setCustomerId(customer_client_id)
                .setPageSize(10000)
                .setQuery("SELECT campaign.id FROM campaign")
                .build();
        GoogleAdsServiceClient.SearchPagedResponse searchPagedResponse = googleAdsServiceClient.search(request);
    }
  • Error logs
2019-08-13 16:56:20.178  WARN 14560 --- [          Gax-1] c.g.ads.googleads.lib.request.summary    : FAILURE REQUEST SUMMARY. Method: google.ads.googleads.v2.services.GoogleAdsService/Search, Endpoint: googleads.googleapis.com:443, CustomerID: 5262041796, RequestID: null, ResponseCode: UNAVAILABLE, Fault: Credentials failed to obtain metadata.
2019-08-13 16:56:20.180  INFO 14560 --- [          Gax-1] c.g.ads.googleads.lib.request.detail     : FAILURE REQUEST DETAIL.
Request
-------
MethodName: google.ads.googleads.v2.services.GoogleAdsService/Search
Endpoint: googleads.googleapis.com:443
Headers: {developer-token=REDACTED, login-customer-id=7987822632, x-goog-api-client=gl-java/1.8.0_161 gapic/ gax/1.45.0 grpc/1.21.0}
Body: customer_id: "5262041796"
query: "SELECT campaign.id FROM campaign"
page_size: 10000


Response
--------
Headers: null
Body: null
Failure message: null
Status: Status{code=UNAVAILABLE, description=Credentials failed to obtain metadata, cause=com.google.api.client.http.HttpResponseException: 400 Bad Request
{
  "error": "invalid_grant",
  "error_description": "Bad Request"
}
	at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1070)
	at com.google.auth.oauth2.UserCredentials.refreshAccessToken(UserCredentials.java:193)
	at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:165)
	at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:151)
	at com.google.auth.Credentials.blockingGetToCallback(Credentials.java:113)
	at com.google.auth.Credentials$1.run(Credentials.java:99)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
}.
2019-08-13 16:56:22.746  WARN 14560 --- [          Gax-4] c.g.ads.googleads.lib.request.summary    : FAILURE REQUEST SUMMARY. Method: google.ads.googleads.v2.services.GoogleAdsService/Search, Endpoint: googleads.googleapis.com:443, CustomerID: 5262041796, RequestID: null, ResponseCode: UNAVAILABLE, Fault: Credentials failed to obtain metadata.
2019-08-13 16:56:22.747  INFO 14560 --- [          Gax-4] c.g.ads.googleads.lib.request.detail     : FAILURE REQUEST DETAIL.
Request
-------
MethodName: google.ads.googleads.v2.services.GoogleAdsService/Search
Endpoint: googleads.googleapis.com:443
Headers: {developer-token=REDACTED, login-customer-id=7987822632, x-goog-api-client=gl-java/1.8.0_161 gapic/ gax/1.45.0 grpc/1.21.0}
Body: customer_id: "5262041796"
query: "SELECT campaign.id FROM campaign"
page_size: 10000


Response
--------
Headers: null
Body: null
Failure message: null
Status: Status{code=UNAVAILABLE, description=Credentials failed to obtain metadata, cause=com.google.api.client.http.HttpResponseException: 400 Bad Request
{
  "error": "invalid_grant",
  "error_description": "Bad Request"
}
	at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1070)
	at com.google.auth.oauth2.UserCredentials.refreshAccessToken(UserCredentials.java:193)
	at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:165)
	at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:151)
	at com.google.auth.Credentials.blockingGetToCallback(Credentials.java:113)
	at com.google.auth.Credentials$1.run(Credentials.java:99)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
}.
2019-08-13 16:56:23.128  WARN 14560 --- [          Gax-1] c.g.ads.googleads.lib.request.summary    : FAILURE REQUEST SUMMARY. Method: google.ads.googleads.v2.services.GoogleAdsService/Search, Endpoint: googleads.googleapis.com:443, CustomerID: 5262041796, RequestID: null, ResponseCode: UNAVAILABLE, Fault: Credentials failed to obtain metadata.
2019-08-13 16:56:23.129  INFO 14560 --- [          Gax-1] c.g.ads.googleads.lib.request.detail     : FAILURE REQUEST DETAIL.
Request
-------
MethodName: google.ads.googleads.v2.services.GoogleAdsService/Search
Endpoint: googleads.googleapis.com:443
Headers: {developer-token=REDACTED, login-customer-id=7987822632, x-goog-api-client=gl-java/1.8.0_161 gapic/ gax/1.45.0 grpc/1.21.0}
Body: customer_id: "5262041796"
query: "SELECT campaign.id FROM campaign"
page_size: 10000


Response
--------
Headers: null
Body: null
Failure message: null
Status: Status{code=UNAVAILABLE, description=Credentials failed to obtain metadata, cause=com.google.api.client.http.HttpResponseException: 400 Bad Request
{
  "error": "invalid_grant",
  "error_description": "Bad Request"
}
	at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1070)
	at com.google.auth.oauth2.UserCredentials.refreshAccessToken(UserCredentials.java:193)
	at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:165)
	at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:151)
	at com.google.auth.Credentials.blockingGetToCallback(Credentials.java:113)
	at com.google.auth.Credentials$1.run(Credentials.java:99)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
	at java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
}.
Disconnected from the target VM, address: '127.0.0.1:62310', transport: 'socket'
2019-08-13 16:56:26.095  INFO 14560 --- [       Thread-5] c.m.t.c.processor.AbstractJobProcessor   : Shutting down application...
2019-08-13 16:56:26.096  INFO 14560 --- [       Thread-5] c.m.t.c.processor.AbstractJobProcessor   : Shutdown complete.

Process finished with exit code 130

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Comments: 23 (12 by maintainers)

Most upvoted comments

Hey thanks for the ping. The underlying issue is being investigated here, I’ve added some more debugging info an reopened since I’m pretty sure that’s the root cause.

Have you tried explicitly calling refreshAccessToken() as mentioned in a previous comment? That will fail immediately if you have an invalid refresh token.

Can do this:

UserCredentials credentials = UserCredentials.newBuilder()
                .setClientId(clientId)
                .setClientSecret(clientSecret)
                .setRefreshToken(refreshToken)
                .build();

// if refresh token is invalid, throw exception
AccessToken accessToken = credentials.refreshAccessToken();

GoogleAdsClient.newBuilder()
                .setCredentials(credentials.toBuilder().setAccessToken(accessToken).build())
                .setDeveloperToken(developerToken)
                .setLoginCustomerId(loginCustomerId)
                .build();