apache/beam · error · IllegalArgumentException
Failed to print type: {modStructValue}
Error message
Failed to print type: {modStructValue} What it means
convertModValueProtosToJson builds a struct Value from the modification's fields and prints it to JSON with a JsonFormat printer so TypeCode parsing works. If printing the mod struct Value fails (InvalidProtocolBufferException), IllegalArgumentException "Failed to print type: <modStructValue>" is thrown.
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/changestreams/mapper/ChangeStreamRecordMapper.java:393
String convertModValueProtosToJson(
List<com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.ModValue> modValueProtos,
List<com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.ColumnMetadata>
columnMetadataProtos) {
com.google.protobuf.Struct.Builder modStructValueBuilder =
com.google.protobuf.Struct.newBuilder();
for (com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.ModValue modValueProto :
modValueProtos) {
final String columnName =
columnMetadataProtos.get(modValueProto.getColumnMetadataIndex()).getName();
final Value columnValue = modValueProto.getValue();
modStructValueBuilder.putFields(columnName, columnValue);
}
Value modStructValue = Value.newBuilder().setStructValue(modStructValueBuilder.build()).build();
String modValueJson;
try {
modValueJson = this.printer.print(modStructValue);
} catch (InvalidProtocolBufferException exc) {
throw new IllegalArgumentException("Failed to print type: " + modStructValue);
}
return modValueJson;
}
List<Mod> parseProtoMod(
List<com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.Mod> modProtos,
List<com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.ColumnMetadata>
columnMetadataProtos) {
List<Mod> mods = new ArrayList<>();
for (com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.Mod modProto : modProtos) {
final String keysJson =
convertModValueProtosToJson(modProto.getKeysList(), columnMetadataProtos);
final String oldValuesJson =
convertModValueProtosToJson(modProto.getOldValuesList(), columnMetadataProtos);
final String newValuesJson =
convertModValueProtosToJson(modProto.getNewValuesList(), columnMetadataProtos);
Mod mod = new Mod(keysJson, oldValuesJson, newValuesJson);
mods.add(mod);View on GitHub (pinned to 12126d8942)
Solutions
- Upgrade Beam's Google Cloud Platform connector and google.protobuf/spanner libraries to the latest versions.
- Inspect the printed modStructValue in the message to find the offending Value kind and check the source column's data.
- Reset/re-read the change stream partition from a good timestamp if the record is corrupt.
- Sanitize or convert exotic column types (e.g. commit-time/protobuf columns) to standard supported types in the tracked table.
Defensive patterns
Strategy: try-catch
Validate before calling
try { printer.print(modStructValue); } catch (InvalidProtocolBufferException e) { /* mod value not renderable */ } Try / catch
try { modValueJson = printer.print(modStructValue); } catch (InvalidProtocolBufferException e) {
log.error("Unprintable mod value: {}", modStructValue, e);
} Prevention
- Upgrade client protos when Spanner adds new Value kinds.
- Avoid exotic column types (protobuf columns) in change-streamed tables.
- Monitor for corrupt records and checkpoint/reset partitions from a clean timestamp.
When it happens
Trigger: A Mod's new/old values struct contains Value protos the printer cannot render — unsupported/unknown kind, malformed nested values from a newer Spanner proto, or corrupted mod data in the change stream record.
Common situations: Change stream records containing exotic value kinds (uninterpreted bytes, new types) on an older connector; corrupted rows in the change stream; proto version drift between Spanner server output and client libraries.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- Failed to parse DirectedReadOptions from string: + directedR
- Failed to print type: {columnMetadataProto.getType().toStrin
- Failed to parse record into proto: {row}
- Failed to parse the proto bytes to ChangeStreamRecord proto
- Failed to print type: {row}
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/cad04725ddff4aa7.
Report an issue: GitHub.