apache/beam · error · RuntimeException

exception while retrieving credentials

Error message

exception while retrieving credentials

What it means

While building service-account credentials from a .p12 key file in BigtableConfigTranslator.translateToBigtableConfig, a GeneralSecurityException can be thrown by KeyStore loading or ServiceAccountJwtAccessCredentials construction. The translator wraps it in a RuntimeException('exception while retrieving credentials') so pipeline translation fails fast with the cause attached.

Solutions

  1. Check the chained cause (getCause()) for the underlying GeneralSecurityException to identify the exact keystore problem
  2. Re-download the service account .p12 key from Cloud Console to replace a corrupt file
  3. Switch to Application Default Credentials (omit credential options) so no keystore parsing is needed
  4. Use UserSuppliedCredentialOptions with Credentials built via GoogleCredentials.getApplicationDefault() in your own code

Example fix

// before
BigtableIO.write().withCredentialOptions(BigtableIO.CredentialOptions.serviceAccountCredentialOptions(corruptP12Path, "sa@project.iam.gserviceaccount.com"))
// after
BigtableIO.write().withCredentialOptions(BigtableIO.CredentialOptions.userSuppliedCredentials(GoogleCredentials.getApplicationDefault()))
Defensive patterns

Strategy: try-catch

Validate before calling

if (!new File(p12Path).canRead()) throw new IllegalStateException("Key file unreadable: " + p12Path);

Try / catch

try {
  // pipeline build with service account credential options
} catch (RuntimeException e) {
  if (e.getCause() instanceof GeneralSecurityException) {
    // replace key file or fall back to ADC
    GoogleCredentials adc = GoogleCredentials.getApplicationDefault();
  }
  throw e;
}

Prevention

When it happens

Trigger: keyStore.load() on a malformed/encrypted-corrupt .p12 file, or ServiceAccountJwtAccessCredentials.newBuilder().setPrivateKey(privateKey).build() rejecting the key material; triggered by service-account credential options with an inaccessible or invalid key file.

Common situations: Corrupt or truncated .p12 file, wrong file downloaded (e.g. an HTML error page saved as .p12), JCE provider issues with PKCS12 in restricted environments, key file with unexpected encryption/password.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/369e7a1f79868fe9. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigtable/BigtableConfigTranslator.java:432

              KeyStore keyStore = KeyStore.getInstance("PKCS12");

              try (FileInputStream fin = new FileInputStream(keyFile)) {
                keyStore.load(fin, "notasecret".toCharArray());
              }
              PrivateKey privateKey =
                  (PrivateKey) keyStore.getKey("privatekey", "notasecret".toCharArray());

              if (privateKey == null) {
                throw new IllegalStateException("private key cannot be null");
              }
              Credentials credentials =
                  ServiceAccountJwtAccessCredentials.newBuilder()
                      .setClientEmail(serviceAccount)
                      .setPrivateKey(privateKey)
                      .build();
              builder.setCredentialFactory(FixedCredentialFactory.create(credentials));
            } catch (GeneralSecurityException exception) {
              throw new RuntimeException("exception while retrieving credentials", exception);
            }
            break;
          case SuppliedCredentials:
            Credentials credentials =
                ((CredentialOptions.UserSuppliedCredentialOptions) credOptions).getCredential();
            builder.setCredentialFactory(FixedCredentialFactory.create(credentials));
            break;
          case SuppliedJson:
            CredentialOptions.JsonCredentialsOptions jsonCredentialsOptions =
                (CredentialOptions.JsonCredentialsOptions) credOptions;
            builder.setCredentialFactory(
                FixedCredentialFactory.create(
                    GoogleCredentials.fromStream(jsonCredentialsOptions.getInputStream())));
            break;
          case None:
            // pipelineOptions is ignored
            PipelineOptions pipelineOptions = PipelineOptionsFactory.create();
            builder.setCredentialFactory(NoopCredentialFactory.fromOptions(pipelineOptions));

View on GitHub (pinned to 12126d8942)