{"record":{"id":"5e776af76aaf6a4a","repo":"apache/beam","slug":"unable-to-obtain-credential","errorCode":null,"errorMessage":"Unable to obtain credential","messagePattern":"Unable to obtain credential","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"sdks/java/extensions/google-cloud-platform-core/src/main/java/org/apache/beam/sdk/extensions/gcp/options/GcpOptions.java","lineNumber":342,"sourceCode":"\n  /**\n   * Attempts to load the GCP credentials. See {@link CredentialFactory#getCredential()} for more\n   * details.\n   */\n  class GcpUserCredentialsFactory implements DefaultValueFactory<Credentials> {\n    @Override\n    public Credentials create(PipelineOptions options) {\n      GcpOptions gcpOptions = options.as(GcpOptions.class);\n      try {\n        CredentialFactory factory =\n            InstanceBuilder.ofType(CredentialFactory.class)\n                .fromClass(gcpOptions.getCredentialFactoryClass())\n                .fromFactoryMethod(\"fromOptions\")\n                .withArg(PipelineOptions.class, options)\n                .build();\n        return factory.getCredential();\n      } catch (IOException | GeneralSecurityException e) {\n        throw new RuntimeException(\"Unable to obtain credential\", e);\n      }\n    }\n  }\n\n  /** EnableStreamingEngine defaults to false unless one of the two experiments is set. */\n  class EnableStreamingEngineFactory implements DefaultValueFactory<Boolean> {\n    @Override\n    public Boolean create(PipelineOptions options) {\n      return ExperimentalOptions.hasExperiment(options, STREAMING_ENGINE_EXPERIMENT)\n          || ExperimentalOptions.hasExperiment(options, WINDMILL_SERVICE_EXPERIMENT);\n    }\n  }\n\n  /**\n   * A GCS path for storing temporary files in GCP.\n   *\n   * <p>Its default to {@link PipelineOptions#getTempLocation}.\n   */","sourceCodeStart":324,"sourceCodeEnd":360,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/extensions/google-cloud-platform-core/src/main/java/org/apache/beam/sdk/extensions/gcp/options/GcpOptions.java#L324-L360","documentation":"GcpOptions.getCredentialFactory() builds a credential via the configured CredentialFactoryClass and wraps any IOException or GeneralSecurityException from credential creation in a RuntimeException with this message. It means the library could not construct a valid Google Cloud credential from the pipeline options (e.g. service account key, metadata server, or installed-account flow).","triggerScenarios":"Calling PipelineOptionsFactory-based runs where GcpOptions.getCredential() is invoked and the credential factory's fromOptions().getCredential() throws IOException or GeneralSecurityException: missing/invalid service account JSON key, unreadable key file path, corrupted key, or default-credential lookup failing on a machine without ADC.","commonSituations":"Running a Beam pipeline locally without GOOGLE_APPLICATION_CREDENTIALS set; pointing serviceAccountKeyFile to a missing or malformed JSON key; a key from the wrong project or a revoked service account; firewall blocking the metadata server on GCE.","solutions":["Set --serviceAccountKeyFile (or GOOGLE_APPLICATION_CREDENTIALS) to a valid, downloadable JSON service account key","Run `gcloud auth application-default login` for local development so ADC succeeds","Validate the key JSON parses and the service account is enabled and has roles (e.g. roles/iam.serviceAccountUser, storage access)","If using a custom CredentialFactoryClass, verify fromOptions() does not throw for your options"],"exampleFix":"// before\nPipelineOptions options = PipelineOptionsFactory.create(); // no credentials configured\n// after\noptions.as(GcpOptions.class).setServiceAccountKeyFile(\"/path/to/valid-key.json\");","handlingStrategy":"validation","validationCode":"import com.google.auth.oauth2.GoogleCredentials;\nGoogleCredentials creds = GoogleCredentials.getApplicationDefault(); // throws if ADC unusable\nif (options.as(GcpOptions.class).getServiceAccountKeyFile() != null)\n  if (!new java.io.File(options.as(GcpOptions.class).getServiceAccountKeyFile()).exists())\n    throw new IllegalStateException(\"service account key file missing\");","typeGuard":"boolean hasCredentialSource(GcpOptions o) {\n  return o.getServiceAccountKeyFile() != null || System.getenv(\"GOOGLE_APPLICATION_CREDENTIALS\") != null;\n}","tryCatchPattern":"try {\n  Credential c = GcpOptions.CredentialFactory.createFromOptions(options);\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Unable to obtain credential\")) {\n    throw new IllegalStateException(\"Configure GOOGLE_APPLICATION_CREDENTIALS or --serviceAccountKeyFile\", e);\n  }\n  throw e;\n}","preventionTips":["Set GOOGLE_APPLICATION_CREDENTIALS or --serviceAccountKeyFile before running","Run `gcloud auth application-default login` in dev environments","Validate key JSON with `gcloud auth activate-service-account --key-file=...` in CI","Keep service account keys rotated and enabled"],"tags":["gcp","authentication","credentials","java","beam"],"backgroundTag":"missing-credentials","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}