apache/iceberg · error · UncheckedIOException

Failed to load Google credentials

Error message

Failed to load Google credentials

What it means

GoogleAuthManager.initialize loads Google credentials (service-account file/JSON or Application Default Credentials) and applies scopes. Any IOException during loading is wrapped in UncheckedIOException('Failed to load Google credentials').

Solutions

  1. Verify the credentials file path exists and is readable from the process, or that ADC is configured (gcloud auth application-default login / GOOGLE_APPLICATION_CREDENTIALS)
  2. Validate the service-account JSON is well-formed and the key is not revoked
  3. On GCP infra, attach a service account / enable workload identity instead of shipping key files
  4. Pre-flight credentials at startup so this surfaces before query time

Example fix

// before
String path = properties.get("gcp.credentials-path"); // file may not exist
// after
String path = properties.get("gcp.credentials-path");
if (path != null && !Files.isReadable(Path.of(path))) {
  throw new IllegalArgumentException("Credentials file not readable: " + path);
}
Defensive patterns

Strategy: try-catch

Validate before calling

String path = props.get("gcp.credentials-path");
if (path != null && !Files.isReadable(Path.of(path))) { throw new IllegalArgumentException("Unreadable credentials file: " + path); }

Try / catch

try { authManager.initialize(props); } catch (UncheckedIOException e) { LOG.error("Google credential load failed", e.getCause()); throw e; }

Prevention

When it happens

Trigger: initialize() runs when the credentials file at GCP_CREDENTIALS_PATH_PROPERTY does not exist or is unreadable, the JSON is invalid, or GoogleCredentials.getApplicationDefault() finds no credential source.

Common situations: Wrong/relative path to the service-account key, file permissions, missing GOOGLE_APPLICATION_CREDENTIALS in the runtime container, or no workload identity on GKE.

Related errors


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

Appendix: source

Thrown at gcp/src/main/java/org/apache/iceberg/gcp/auth/GoogleAuthManager.java:118

    try {
      if (useCredentialsPath) {
        LOG.info("Using Google credentials from path: {}", credentialsPath);
        try (FileInputStream credentialsStream = new FileInputStream(credentialsPath)) {
          this.credentials = GoogleCredentials.fromStream(credentialsStream).createScoped(scopes);
        }
      } else if (useCredentialsJson) {
        LOG.info("Using Google credentials from json");
        try (InputStream credentialsStream =
            new ByteArrayInputStream(credentialsJson.getBytes(StandardCharsets.UTF_8))) {
          this.credentials = GoogleCredentials.fromStream(credentialsStream).createScoped(scopes);
        }
      } else {
        LOG.info("Using Application Default Credentials with scopes: {}", scopesString);
        this.credentials = GoogleCredentials.getApplicationDefault().createScoped(scopes);
      }
    } catch (IOException e) {
      throw new UncheckedIOException("Failed to load Google credentials", e);
    }

    this.initialized = true;
  }

  /**
   * Initializes and returns a short-lived session, typically for fetching configuration. This
   * implementation reuses the long-lived catalog session logic.
   */
  @Override
  public AuthSession initSession(RESTClient initClient, Map<String, String> properties) {
    return catalogSession(initClient, properties);
  }

  /**
   * Returns a long-lived session tied to the catalog's lifecycle. This session uses Google
   * Application Default Credentials or a specified service account.
   *

View on GitHub (pinned to 86d9c8fc54)