apache/iceberg · error · IllegalStateException

Failed to obtain Google access token. Cannot authenticate…

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.

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.

Appendix: 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)