apache/beam · critical · RuntimeException
Unable to obtain credential
Error message
Unable to obtain credential
What it means
GoogleAdsOptions' credential factory wraps IOException/GeneralSecurityException from instantiating and invoking the configured GoogleAdsCredentialFactory in a RuntimeException 'Unable to obtain credential'. It means the OAuth credential for the Google Ads connector could not be created from pipeline options.
Solutions
- Verify credentials are configured (googleApplicationCredentials / GOOGLE_APPLICATION_CREDENTIALS) and the JSON is valid and unexpired
- Check the custom GoogleAdsCredentialFactoryClass implementation for errors in fromOptions
- Inspect the cause chain (IOException/GeneralSecurityException) for the root reason
- Confirm scopes and developer token are valid for the account
Example fix
// before --defaultWorkerHarnessContainerImage... options without credentials // after options.setGcpCredential(SecretHelper.getCredential()); // or set GOOGLE_APPLICATION_CREDENTIALS=/path/sa.json
Defensive patterns
Strategy: try-catch
Validate before calling
Preconditions.checkNotNull(options.getGoogleAdsCredentialFactoryClass(), "credential factory not set"); Preconditions.checkNotNull(options.getGcpCredential() == null && System.getenv("GOOGLE_APPLICATION_CREDENTIALS") == null ? null : Boolean.TRUE, "no credentials configured"); Try / catch
try { GoogleAdsIO.read().from(...).expand(p); } catch (RuntimeException e) { if ("Unable to obtain credential".equals(e.getMessage())) { reconfigureCredentials(); } else throw e; } Prevention
- Set GOOGLE_APPLICATION_CREDENTIALS or options.setGcpCredential before launch
- Validate the service-account JSON loads in a smoke test
- Keep developer token and scopes current
When it happens
Trigger: Calling the GoogleAdsIO read with options whose gcpCredential/clientSecrets cannot be loaded: missing/invalid service account key, bad secrets file path, or a factory's fromOptions throwing.
Common situations: Missing GOOGLE_APPLICATION_CREDENTIALS, expired or malformed service-account JSON, wrong scopes, network/clock issues during token exchange.
Related errors
- GCP Authentication Extension not configured properly
- Unable to get Google Ads response after retrying
- A function must be provided to convert the input type into…
- A PValue contained in
- A schema was provided without a data format (or viceversa)…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/a281ecb7af5bd12e.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/google-ads/src/main/java/org/apache/beam/sdk/io/googleads/GoogleAdsOptions.java:126
/**
* Attempts to load the Google Ads credentials. See {@link CredentialFactory#getCredential()} for
* more details.
*/
class GoogleAdsCredentialsFactory implements DefaultValueFactory<@Nullable Credentials> {
@Override
public @Nullable Credentials create(PipelineOptions options) {
GoogleAdsOptions googleAdsOptions = options.as(GoogleAdsOptions.class);
try {
CredentialFactory factory =
InstanceBuilder.ofType(CredentialFactory.class)
.fromClass(googleAdsOptions.getGoogleAdsCredentialFactoryClass())
.fromFactoryMethod("fromOptions")
.withArg(PipelineOptions.class, options)
.build();
return factory.getCredential();
} catch (IOException | GeneralSecurityException e) {
throw new RuntimeException("Unable to obtain credential", e);
}
}
}
}
View on GitHub (pinned to 12126d8942)