apache/beam · error · IllegalArgumentException

Failed to print type: {columnMetadataProto.getType().toStrin

Error message

Failed to print type: {columnMetadataProto.getType().toString()}

What it means

In parseProtoColumnMetadata, the connector prints the column's Type proto to its JSON form (e.g. {"code":"INT64"}) using a JsonFormat printer to feed the TypeCode class. If the Type proto is invalid/unprintable (InvalidProtocolBufferException), it throws IllegalArgumentException with the proto's toString.

Source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/changestreams/mapper/ChangeStreamRecordMapper.java:361

        dataChangeRecordProto.getNumberOfRecordsInTransaction(),
        dataChangeRecordProto.getNumberOfPartitionsInTransaction(),
        dataChangeRecordProto.getTransactionTag(),
        dataChangeRecordProto.getIsSystemTransaction(),
        changeStreamRecordMetadataFrom(partition, commitTimestamp, resultSetMetadata));
  }

  List<ColumnType> parseProtoColumnMetadata(
      List<com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.ColumnMetadata>
          columnMetadataProtos) {
    List<ColumnType> columnTypes = new ArrayList<>();
    for (com.google.spanner.v1.ChangeStreamRecord.DataChangeRecord.ColumnMetadata
        columnMetadataProto : columnMetadataProtos) {
      // TypeCode class takes json format argument in its constructor, e.g. `{\"code\":\"INT64\"}`.
      String typeCodeJson;
      try {
        typeCodeJson = this.printer.print(columnMetadataProto.getType());
      } catch (InvalidProtocolBufferException exc) {
        throw new IllegalArgumentException(
            "Failed to print type: " + columnMetadataProto.getType().toString());
      }
      ColumnType columnType =
          new ColumnType(
              columnMetadataProto.getName(),
              new TypeCode(typeCodeJson),
              columnMetadataProto.getIsPrimaryKey(),
              columnMetadataProto.getOrdinalPosition());
      columnTypes.add(columnType);
    }
    return columnTypes;
  }

  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 =

View on GitHub (pinned to 12126d8942)

Solutions

  1. Upgrade the Beam Spanner connector and its google.spanner.v1 protos so JsonFormat can print all Type variants.
  2. Log/print columnMetadataProto.getType() to identify the malformed field and check the originating change stream record.
  3. Re-read the partition or reset from an earlier timestamp if the metadata record is corrupt.
  4. Confirm the column's type is a standard Spanner type supported by the change stream mapper.
Defensive patterns

Strategy: try-catch

Validate before calling

try { printer.print(columnMetadataProto.getType()); } catch (InvalidProtocolBufferException e) { /* flag record before mapping */ }

Try / catch

try { typeCodeJson = printer.print(columnMetadataProto.getType()); } catch (InvalidProtocolBufferException e) {
  log.error("Unprintable column type: {}", columnMetadataProto.getType(), e);
}

Prevention

When it happens

Trigger: A DataChangeRecord's column metadata contains a Type proto that the JsonFormat printer rejects — malformed any-value payloads, unexpected proto fields from a newer Spanner format, or corrupted metadata bytes.

Common situations: Connector/protos version mismatch where the printer's type registry lacks the embedded Type message; corrupted change stream metadata rows; PG-dialect type definitions the older proto can't render.

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


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