apache/beam · error · IllegalArgumentException
Unable to retrieve schema for table
Error message
Unable to retrieve schema for table %s. Found only tables: [%s]
What it means
Thrown by spannerSchemaToBeamSchema when the fetched SpannerSchema does not contain any table whose name equals (case-insensitively) the requested tableName. The provider cannot map a Beam Schema without the table's row definition, so it fails fast with the list of tables it does know.
Solutions
- Compare the tableName in the error message against the 'Found only tables' list and fix the configuration to use an exact (case-insensitive) match.
- Verify the change stream is created on (or watches) the table you configured to read.
- Re-check the database configuration — connecting to the wrong Spanner database yields a schema lacking your table.
- If the table was renamed, update the pipeline configuration to the new table name.
Example fix
// before
.setTable("orders") // found tables: [Order]
// after
.setTable("Order") // or correct the actual table name in Spanner Defensive patterns
Strategy: validation
Validate before calling
boolean exists = spannerSchema.getTables().stream()
.anyMatch(t -> t.equalsIgnoreCase(tableName));
if (!exists) throw new IllegalArgumentException("Unknown table: " + tableName); Try / catch
try { schema = provider.expand(config); } catch (IllegalArgumentException e) { /* table list is in the message; reconfigure and retry */ } Prevention
- Copy table names from the 'Found only tables' list verbatim into your configuration.
- Confirm the change stream is created over the exact table you read.
- Update configs when tables are renamed or dropped.
When it happens
Trigger: Calling getTableSchema with a table name that is absent from the SpannerSchema captured by the change stream pipeline; requesting a table the change stream does not cover; a case/whitespace mismatch between config table name and the actual table name.
Common situations: Typo in table name in the Spanner change stream configuration; change stream created over a different table than configured; renamed/dropped table while the pipeline config still references the old name.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Cannot find Spanner table.
- Error processing struct to row
- Exception while trying to retrieve schema
- Exception while trying to retrieve schema
- Invalid ARRAY type: + originalSpannerType
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/1ce8a4b7a62c2437.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/changestreams/SpannerChangestreamsReadSchemaTransformProvider.java:353
.setCoder(StringUtf8Coder.of());
miniPipeline.run().waitUntilFinish();
// Clean up the static map from the object.
SpannerSchema finalSchemaObj = TABLE_SCHEMAS.remove(config.getTable());
if (finalSchemaObj == null) {
throw new RuntimeException(
String.format("Could not get schema for configuration %s", config));
}
return spannerSchemaToBeamSchema(finalSchemaObj, config.getTable());
}
private static Schema spannerSchemaToBeamSchema(
SpannerSchema spannerSchema, final String tableName) {
OptionalInt optionalIdx =
IntStream.range(0, spannerSchema.getTables().size())
.filter(idx -> spannerSchema.getTables().get(idx).equalsIgnoreCase(tableName))
.findAny();
if (!optionalIdx.isPresent()) {
throw new IllegalArgumentException(
String.format(
"Unable to retrieve schema for table %s. Found only tables: [%s]",
tableName, String.join(", ", spannerSchema.getTables())));
}
Schema.Builder schemaBuilder = Schema.builder();
String spannerTableName = spannerSchema.getTables().get(optionalIdx.getAsInt());
for (SpannerSchema.Column col : spannerSchema.getColumns(spannerTableName)) {
schemaBuilder =
schemaBuilder.addNullableField(col.getName(), spannerTypeToBeamType(col.getType()));
}
schemaBuilder =
schemaBuilder.setOptions(
Schema.Options.builder()
.setOption(
"primaryKeyColumns",View on GitHub (pinned to 12126d8942)