apache/beam · error · IllegalArgumentException

Unsupported CDC ValueKind: {}

Error message

Unsupported CDC ValueKind: {}

What it means

CdcOutputUtils.changelogOperation maps a CDC ValueKind enum to the Iceberg ChangelogOperation written into the output metadata. The mapping covers INSERT, DELETE, UPDATE_BEFORE and UPDATE_AFTER; any other ValueKind has no defined mapping and throws IllegalArgumentException.

Source

Thrown at sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/cdc/CdcOutputUtils.java:192

    }
    if (dataAndRowMetadata.getSchema().hasField(metadataColumn)) {
      return dataAndRowMetadata.getValue(metadataColumn);
    }
    return null;
  }

  private static ChangelogOperation changelogOperation(ValueKind valueKind) {
    switch (valueKind) {
      case INSERT:
        return ChangelogOperation.INSERT;
      case DELETE:
        return ChangelogOperation.DELETE;
      case UPDATE_BEFORE:
        return ChangelogOperation.UPDATE_BEFORE;
      case UPDATE_AFTER:
        return ChangelogOperation.UPDATE_AFTER;
      default:
        throw new IllegalArgumentException("Unsupported CDC ValueKind: " + valueKind);
    }
  }
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Upgrade the Beam Iceberg CDC library to a version whose enum mapping matches the producer's ValueKind set.
  2. Sanitize/normalize input records upstream so only INSERT/DELETE/UPDATE_BEFORE/UPDATE_AFTER reach the transform.
  3. Log and drop or dead-letter unknown ValueKind records in a pre-transform instead of letting them fail the pipeline.
  4. Check the source connector (e.g. Debezium op codes) mapping to ensure it does not emit unhandled kinds.

Example fix

// before
records.apply(CdcOutputUtils.toIcebergChangelog(...)); // producer emits TRUNCATE kind
// after
records.apply("filter-kinds", Filter.by(r ->
    EnumSet.of(ValueKind.INSERT, ValueKind.DELETE, ValueKind.UPDATE_BEFORE, ValueKind.UPDATE_AFTER)
        .contains(r.getKind())))
  .apply(CdcOutputUtils.toIcebergChangelog(...));
Defensive patterns

Strategy: validation

Validate before calling

Set<ValueKind> allowed = EnumSet.of(ValueKind.INSERT, ValueKind.DELETE, ValueKind.UPDATE_BEFORE, ValueKind.UPDATE_AFTER);
if (!allowed.contains(record.getKind())) {
  throw new IllegalArgumentException("Unmapped ValueKind: " + record.getKind());
}

Type guard

boolean isKnownKind(ValueKind k) {
  return k == ValueKind.INSERT || k == ValueKind.DELETE || k == ValueKind.UPDATE_BEFORE || k == ValueKind.UPDATE_AFTER;
}

Try / catch

try {
  records.apply(CdcOutputUtils.toIcebergChangelog(...));
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Unsupported CDC ValueKind")) {
    // route record to dead-letter and continue
  } else { throw e; }
}

Prevention

When it happens

Trigger: A CDC record whose ValueKind is not one of the four enumerated kinds (e.g. a new/truncated kind added upstream, or a corrupted/unknown enum ordinal deserialized from the source) flows into changelogOperation via metadataValue.

Common situations: Version skew between the CDC producer writing ValueKind and the Beam Iceberg CDC library reading it; hand-crafted or corrupted input records feeding the transform; schema/enum evolution upstream.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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