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
- Check the chained cause (getCause()) for the underlying GeneralSecurityException to identify the exact keystore problem
- Re-download the service account .p12 key from Cloud Console to replace a corrupt file
- Switch to Application Default Credentials (omit credential options) so no keystore parsing is needed
- 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
- Fall back to Application Default Credentials in GCP environments (Dataflow, GCE) instead of key files
- Validate .p12 files load with keytool before deployment
- Log the cause chain to distinguish corrupt files from provider issues
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
- Exception getting credentials
- private key cannot be null
- Bigtable location must be in the following format…
- Builder method has to be explicitly allowed
- Builder method name has to be explicitly allowed
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)