apache/beam · error · IllegalArgumentException

Failed to print type: {row}

Error message

Failed to print type: {row}

What it means

columnTypeJsonFrom converts a JSON row describing a Spanner column type into a ColumnType proto, using a proto printer on extracted fields. If printer.apt/ printing throws InvalidProtocolBufferException, the row's JSON values are malformed for the expected proto-JSON schema and the mapper throws 'Failed to print type'. This signals that the row does not match the expected change stream column-type structure.

Source

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

    try {
      final String type =
          this.printer.print(
              Optional.ofNullable(valueMap.get(TYPE_COLUMN))
                  .orElseThrow(IllegalArgumentException::new));
      return new ColumnType(
          Optional.ofNullable(valueMap.get(NAME_COLUMN))
              .orElseThrow(IllegalArgumentException::new)
              .getStringValue(),
          new TypeCode(type),
          Optional.ofNullable(valueMap.get(IS_PRIMARY_KEY_COLUMN))
              .orElseThrow(IllegalArgumentException::new)
              .getBoolValue(),
          (long)
              Optional.ofNullable(valueMap.get(ORDINAL_POSITION_COLUMN))
                  .orElseThrow(IllegalArgumentException::new)
                  .getNumberValue());
    } catch (InvalidProtocolBufferException exc) {
      throw new IllegalArgumentException("Failed to print type: " + row);
    }
  }

  private Mod modFrom(Struct struct) {
    final String keys = struct.getJson(KEYS_COLUMN);
    final String oldValues =
        struct.isNull(OLD_VALUES_COLUMN) ? null : struct.getJson(OLD_VALUES_COLUMN);
    final String newValues =
        struct.isNull(NEW_VALUES_COLUMN) ? null : struct.getJson(NEW_VALUES_COLUMN);
    return new Mod(keys, oldValues, newValues);
  }

  private Mod modJsonFrom(Value row) {
    try {
      Map<String, Value> valueMap = row.getStructValue().getFieldsMap();
      final String keys =
          this.printer.print(
              Optional.ofNullable(valueMap.get(KEYS_COLUMN))

View on GitHub (pinned to 12126d8942)

Solutions

  1. Verify the row contains the expected columns (TYPE, ORDINAL_POSITION, etc.) as valid proto-JSON.
  2. Check that values were parsed with this.parser before being passed to the printer — do not pass raw strings.
  3. Align SDK version: regenerate/refresh rows with the same Beam version that will read them.
  4. Wrap the mapping call in try-catch to surface the offending row without killing the pipeline.
  5. Inspect the row content in the exception message for missing/invalid fields.

Example fix

// before
ColumnType type = mapper.columnTypeJsonFrom(row); // throws on malformed row

// after
try {
  ColumnType type = mapper.columnTypeJsonFrom(row);
} catch (IllegalArgumentException e) {
  LOG.error("Skipping malformed column-type row: %s", e.getMessage());
}
Defensive patterns

Strategy: try-catch

Validate before calling

boolean hasRequiredColumnTypeFields(java.util.Map<String, com.google.protobuf.Value> map) {
  return map != null && map.containsKey("TYPE") && map.containsKey("ORDINAL_POSITION");
}

Type guard

boolean isNonNullJsonTypeValue(com.google.protobuf.Value v) {
  return v != null && v.getKindCase() == com.google.protobuf.Value.KindCase.STRING_VALUE;
}

Try / catch

try {
  ColumnType t = columnTypeJsonFrom(row);
} catch (IllegalArgumentException e) {
  LOG.error("Cannot map column type row: %s", e.getMessage());
}

Prevention

When it happens

Trigger: Calling columnTypeJsonFrom with a row whose TYPE/ORDINAL_POSITION etc. fields are not valid proto-JSON Value messages, so the protobuf printer throws while serializing; also triggered when required keys resolve to Value objects incompatible with the printer.

Common situations: Malformed or hand-crafted test fixtures; rows produced by a different Spanner schema/connector version; corrupted metadata rows; passing wrong Value maps (e.g. missing or wrongly-typed fields) into the mapper.

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/a2ec5f20280ba48b. Report an issue: GitHub.