apache/beam · error · IllegalStateException

pipeline options cannot be null

Error message

pipeline options cannot be null

What it means

In DynamicDestinationsHelpers (table-creation helper), when resolving a BigQuery table the code fetches PipelineOptions via getPipelineOptions(); if null, IllegalStateException "pipeline options cannot be null" is thrown because project/projectId resolution requires BigQueryOptions.

Solutions

  1. Set PipelineOptions on the object before the call (the helper's setPipelineOptions/setup path) — ensure BigQueryIO.Write pipeline setup runs it from the ProcessContext
  2. In tests, call the options setter with TestPipeline.testingPipelineOptions() or PipelineOptionsFactory.create() before invoking existingTable
  3. Ensure project ID is set explicitly on the TableReference so options-based defaulting isn't needed
  4. Check that the DoFn's setup/startBundle wiring (setPipelineOptionsFromProcessContext) is not skipped

Example fix

// before: invoking helper in a test without options
BigQueryServices.StorageClient ... helper = new TableSchemaUpdateTransaction(...);
helper.existingTable(ref);
// after
PipelineOptions options = PipelineOptionsFactory.create().as(BigQueryOptions.class);
options.setProject("my-project");
helper.setPipelineOptions(options);
helper.existingTable(ref);
Defensive patterns

Strategy: validation

Validate before calling

if (helper.getPipelineOptions() == null) {
  helper.setPipelineOptions(PipelineOptionsFactory.create().as(BigQueryOptions.class));
}

Type guard

boolean hasPipelineOptions(DynamicDestinations<?, ?> dd) { return dd.getPipelineOptions() != null; }

Try / catch

try { table = helper.existingTable(ref); } catch (IllegalStateException e) { LOG.error("Pipeline options missing: %s", e.getMessage()); throw e; }

Prevention

When it happens

Trigger: Calling existingTable/getBigQueryTable when the DynamicDestinations helper has no PipelineOptions set — typically when getPipelineOptions() was never wired from a DoFn.ProcessContext (options are set at pipeline setup), or invoking the helper outside a running pipeline (unit tests, direct construction).

Common situations: Unit-testing DynamicDestinations destinations without setting pipeline options; calling table-lookup helpers during pipeline construction before options are distributed; forgetting options.setPipelineOptions in the DoFn setup; serialized helper losing the options field.

Related errors


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

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/DynamicDestinationsHelpers.java:446

        DynamicDestinations<T, DestinationT> inner, BigQueryServices bqServices) {
      super(inner);
      this.bqServices = bqServices;
    }

    private @Nullable Table getBigQueryTable(TableReference tableReference) {
      BackOff backoff =
          BackOffAdapter.toGcpBackOff(
              FluentBackoff.DEFAULT
                  .withMaxRetries(3)
                  .withInitialBackoff(Duration.standardSeconds(1))
                  .withMaxBackoff(Duration.standardSeconds(2))
                  .backoff());
      try {
        do {
          try {
            PipelineOptions options = getPipelineOptions();
            if (options == null) {
              throw new IllegalStateException("pipeline options cannot be null");
            }
            BigQueryOptions bqOptions = options.as(BigQueryOptions.class);
            if (tableReference.getProjectId() == null) {
              tableReference.setProjectId(
                  bqOptions.getBigQueryProject() == null
                      ? bqOptions.getProject()
                      : bqOptions.getBigQueryProject());
            }
            try (DatasetService datasetService = bqServices.getDatasetService(bqOptions)) {
              return datasetService.getTable(tableReference);
            } catch (InterruptedException | IOException e) {
              LOG.info("Failed to get BigQuery table {}", tableReference);
            }
          } catch (Exception e) {
            throw new RuntimeException(e);
          }
        } while (nextBackOff(Sleeper.DEFAULT, backoff));
      } catch (InterruptedException e) {

View on GitHub (pinned to 12126d8942)