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.

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.

Appendix: 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)