apache/beam · error · IllegalArgumentException
MetadataInstance can't be empty
Error message
MetadataInstance can't be empty
What it means
Thrown by ChangeStreamReaderBuilder.build() when building a Spanner change-stream read: the configured metadataInstance is an empty string. The metadata instance is the Cloud Spanner instance where the connector stores change-stream connector metadata (heartbeats, partitions state). The library refuses to construct the transform without it because writes would fail downstream.
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/SpannerTransformRegistrar.java:503
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);
if (configuration.inclusiveStartAt != null) {
readChangeStream = readChangeStream.withInclusiveStartAt(configuration.inclusiveStartAt);
}View on GitHub (pinned to 12126d8942)
Solutions
- Set withMetadataInstance("your-instance") (or fill the metadataInstance field in your pipeline options) with a valid Cloud Spanner instance ID.
- If metadata should live in the same instance as the change stream, copy the instanceId value into metadataInstance.
- Validate configuration before submitting the pipeline so the failure surfaces at config time rather than at graph construction.
Example fix
// before
SpannerIO.readChangeStream()
.withProjectId(project)
.withInstanceId(instance)
.withMetadataInstance("")
// after
SpannerIO.readChangeStream()
.withProjectId(project)
.withInstanceId(instance)
.withMetadataInstance(instance) Defensive patterns
Strategy: validation
Validate before calling
// before building
if (metadataInstance == null || metadataInstance.isEmpty()) {
throw new IllegalArgumentException("metadataInstance must be set to a non-empty Spanner instance ID");
} Prevention
- Always set withMetadataInstance alongside withInstanceId; reuse instanceId if no separate metadata instance exists.
- Validate pipeline options in main() before Pipeline.create().
- Fail fast on blank strings from templated parameters using ValueProvider checks where possible.
When it happens
Trigger: Calling SpannerIO.readChangeStream() (or a ChangeStreamReaderBuilder via the transform registrar) and setting withMetadataInstance("") or never calling withMetadataInstance at all while the surrounding config leaves the field empty, then invoking build().
Common situations: YAML/JSON pipeline options where the metadataInstance key is present but empty; templated pipelines with a blank parameter; copying a pipeline config that had instanceId but forgot the separate metadataInstance field.
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
- MetadataDatabase can't be empty
- Unrecognized dialect: + dialect.name()
- Experimental host can only be used with instance id: + EXPER
- Failed to parse DirectedReadOptions from string: + directedR
- Start time cannot be after end time.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/80222dcab0f6abaa.
Report an issue: GitHub.