apache/iceberg · error · IllegalStateException

Failed to obtain Google access token. Cannot authenticate re

Error message

Failed to obtain Google access token. Cannot authenticate request.

What it means

GoogleAuthSession.authenticate adds a Bearer token to outgoing requests. If the refreshed credentials yield no token (token blocking returns null/absent), it throws IllegalStateException('Failed to obtain Google access token. Cannot authenticate request.') because the request cannot be authorized.

Source

Thrown at gcp/src/main/java/org/apache/iceberg/gcp/auth/GoogleAuthSession.java:77

  @Override
  public HTTPRequest authenticate(HTTPRequest request) {
    try {
      credentials.refreshIfExpired();
      AccessToken token = credentials.getAccessToken();

      if (token != null && token.getTokenValue() != null) {
        HTTPHeaders newHeaders =
            request
                .headers()
                .putIfAbsent(
                    HTTPHeaders.of(
                        HTTPHeaders.HTTPHeader.of(
                            "Authorization", "Bearer " + token.getTokenValue())));
        return newHeaders.equals(request.headers())
            ? request
            : ImmutableHTTPRequest.builder().from(request).headers(newHeaders).build();
      } else {
        throw new IllegalStateException(
            "Failed to obtain Google access token. Cannot authenticate request.");
      }
    } catch (IOException e) {
      LOG.error("IOException while trying to refresh Google access token", e);
      throw new UncheckedIOException("Failed to refresh Google access token", e);
    }
  }

  /**
   * Closes the session. This is a no-op for GoogleAuthSession as the lifecycle of GoogleCredentials
   * is not managed by this session.
   */
  @Override
  public void close() {
    // No-op
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure initialize() ran and credentials have the required scopes before authenticating requests
  2. Force a refresh and check token expiry: credentials.refreshIfExpired() then assert getAccessToken() != null
  3. Check system clock skew (NTP) which can invalidate cached tokens
  4. Replace the session/credentials object if it is in a permanently unauthenticated state

Example fix

// before
Credentials creds = GoogleCredentials.getApplicationDefault(); // no scopes
// after
Credentials creds = GoogleCredentials.getApplicationDefault().createScoped(requiredScopes);
creds.refreshIfExpired();
Preconditions.checkState(creds.getAccessToken() != null, "No access token");
Defensive patterns

Strategy: try-catch

Validate before calling

if (credentials.getAccessToken() == null || isExpired(credentials.getAccessToken())) { credentials.refreshIfExpired(); }
if (credentials.getAccessToken() == null) { throw new IllegalStateException("Token unavailable before request"); }

Try / catch

try { request = session.authenticate(request); } catch (IllegalStateException e) { LOG.error("No Google access token — re-initialize session", e); throw e; }

Prevention

When it happens

Trigger: authenticate(request) is called but credentials.refreshIfExpired()/getToken() produces no usable AccessToken — e.g. credentials never initialized, refresh silently skipped, or the credential instance cannot block for a token.

Common situations: Clock skew on the client machine, credentials object constructed without scopes required by the API, or a session used before GoogleAuthManager.initialize completed.

Understand the failure class

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/599dd221bebe1899. Report an issue: GitHub.