apache/iceberg · error · UncheckedIOException

Failed to refresh Google access token

Error message

Failed to refresh Google access token

What it means

In GoogleAuthSession.authenticate, refreshing the Google credentials can throw IOException (network failure, auth server error, revoked key). The exception is logged and rethrown as UncheckedIOException('Failed to refresh Google access token').

Source

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

      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. Check network access to oauth2.googleapis.com from the runtime environment
  2. Verify the service-account key is still valid and not revoked in IAM
  3. Retry with backoff for transient network/5xx errors before failing the request
  4. Confirm scopes/audience configuration in GoogleAuthManager matches the API being called

Example fix

// before
request = session.authenticate(request); // throws on first transient refresh failure
// after
try {
  request = session.authenticate(request);
} catch (UncheckedIOException e) {
  Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
  request = session.authenticate(request); // retry once
}
Defensive patterns

Strategy: retry

Validate before calling

// verify token endpoint reachable
HttpResponse<String> r = HttpClient.newHttpClient().send(RequestBuilder.get("https://oauth2.googleapis.com/token").build(), BodyHandlers.ofString());

Try / catch

try { request = session.authenticate(request); } catch (UncheckedIOException e) { /* retry with backoff, then surface */ Uninterruptibles.sleepUninterruptibly(1, TimeUnit.SECONDS); request = session.authenticate(request); }

Prevention

When it happens

Trigger: authenticate(request) triggers token refresh (refreshIfExpired/refresh) and the HTTP call to Google's OAuth endpoints fails or the credential's token endpoint rejects the request.

Common situations: Network egress to oauth2.googleapis.com blocked, expired/revoked service-account key, incorrect audience or scopes, transient 5xx from Google's token endpoint, or DNS/proxy failures.

Related errors


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