apache/beam · error · IllegalArgumentException

ChangeStreamName can't be empty

Error message

ChangeStreamName can't be empty

What it means

In buildExternal() for the Spanner change-stream reader, after checkMandatoryFields() the configuration's changeStreamName is checked and this IllegalArgumentException is thrown when it is empty. Reading a Cloud Spanner change stream requires the exact name of an existing change stream, so an empty name cannot be dispatched to the Spanner API.

Source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerTransformRegistrar.java:499

        }
      }

      public void setWatermarkRefreshRate(@Nullable String watermarkRefreshRateString) {
        if (watermarkRefreshRateString != null) {
          this.watermarkRefreshRate = Duration.parse(watermarkRefreshRateString);
        }
      }
    }

    @Override
    @NonNull
    public PTransform<PBegin, PCollection<String>> buildExternal(
        ChangeStreamReaderBuilder.Configuration configuration) {

      configuration.checkMandatoryFields();

      if (configuration.changeStreamName.isEmpty()) {
        throw new IllegalArgumentException("ChangeStreamName can't be empty");
      }

      if (configuration.metadataInstance.isEmpty()) {
        throw new IllegalArgumentException("MetadataInstance can't be empty");
      }

      if (configuration.metadataDatabase.isEmpty()) {
        throw new IllegalArgumentException("MetadataDatabase can't be empty");
      }

      SpannerIO.ReadChangeStream readChangeStream =
          SpannerIO.readChangeStream()
              .withProjectId(configuration.projectId)
              .withInstanceId(configuration.instanceId)
              .withDatabaseId(configuration.databaseId)
              .withChangeStreamName(configuration.changeStreamName)
              .withMetadataInstance(configuration.metadataInstance)
              .withMetadataDatabase(configuration.metadataDatabase);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Set the change stream name in the configuration (non-empty), matching `gcloud spanner change-streams list` output.
  2. Verify any templated value (env var/parameter substitution) actually resolved to a non-empty string.
  3. Add a pre-build validation that changeStreamName is non-null and non-empty.

Example fix

// before
{"changeStreamName": "", "metadataInstance": "meta-i"}
// after
{"changeStreamName": "my-stream", "metadataInstance": "meta-i"}
Defensive patterns

Strategy: validation

Validate before calling

if (changeStreamName == null || changeStreamName.isEmpty()) { throw new IllegalArgumentException("changeStreamName must be provided to read a change stream"); }

Try / catch

try { external.buildExternal(config); } catch (IllegalArgumentException e) { throw new ConfigException("Change stream config incomplete: " + e.getMessage(), e); }

Prevention

When it happens

Trigger: Building the ChangeStreamReader external transform with configuration.changeStreamName empty or unset — e.g. a pipeline spec where the changeStreamName key is missing, blank, or the value failed to interpolate.

Common situations: Hand-written JSON/YAML pipeline templates missing the change stream name; templating engines leaving ${CHANGE_STREAM} unexpanded or empty; users confusing the change stream name with the table name.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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