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
- Set PipelineOptions on the object before the call (the helper's setPipelineOptions/setup path) — ensure BigQueryIO.Write pipeline setup runs it from the ProcessContext
- In tests, call the options setter with TestPipeline.testingPipelineOptions() or PipelineOptionsFactory.create() before invoking existingTable
- Ensure project ID is set explicitly on the TableReference so options-based defaulting isn't needed
- 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
- Ensure BigQueryIO.Write's setup path wires pipeline options from the ProcessContext
- In tests, always inject TestPipeline.testingPipelineOptions() before calling table helpers
- Set the project ID explicitly on TableReferences to reduce options dependence
- Check that serialized helper objects retain (or re-set) options after deserialization
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
- Reader returned null element
- Received 'None' as the value for the field
- Received null value for non-nullable field " +…
- sideInputAccessor (transient field) is null
- Unexpected status [ ] of load job: .
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)