apache/iceberg · error · IllegalArgumentException

Source table %s contains one/all of the reserved property ke

Error message

Source table %s contains one/all of the reserved property keys: %s, %s.

What it means

getTable injects the reserved Flink property keys (connector and src-catalog) into the returned property map to support CREATE TABLE LIKE. If the stored Iceberg table itself already contains one of these reserved keys, Iceberg refuses and throws IllegalArgumentException to prevent property collision and corrupted round-trips. The keys are FlinkCreateTableOptions.CONNECTOR_PROPS_KEY and SRC_CATALOG_PROPS_KEY.

Source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/FlinkCatalog.java:349

  }

  @Override
  public CatalogTable getTable(ObjectPath tablePath)
      throws TableNotExistException, CatalogException {
    Table table = loadIcebergTable(tablePath);

    // Flink's CREATE TABLE LIKE clause relies on properties sent back here to create new table.
    // As Flink API accepts only Map<String, String> for props, here we are serializing catalog
    // name, database, table as json string to distinguish between catalog info
    // and table properties in createTable.
    String srcCatalogProps =
        FlinkCreateTableOptions.toJson(
            getName(), tablePath.getDatabaseName(), tablePath.getObjectName());

    Map<String, String> tableProps = table.properties();
    if (tableProps.containsKey(FlinkCreateTableOptions.CONNECTOR_PROPS_KEY)
        || tableProps.containsKey(FlinkCreateTableOptions.SRC_CATALOG_PROPS_KEY)) {
      throw new IllegalArgumentException(
          String.format(
              "Source table %s contains one/all of the reserved property keys: %s, %s.",
              tablePath,
              FlinkCreateTableOptions.CONNECTOR_PROPS_KEY,
              FlinkCreateTableOptions.SRC_CATALOG_PROPS_KEY));
    }

    ImmutableMap.Builder<String, String> mergedProps = ImmutableMap.builder();
    mergedProps.put(
        FlinkCreateTableOptions.CONNECTOR_PROPS_KEY, FlinkDynamicTableFactory.FACTORY_IDENTIFIER);
    mergedProps.put(FlinkCreateTableOptions.SRC_CATALOG_PROPS_KEY, srcCatalogProps);
    mergedProps.putAll(tableProps);

    return toCatalogTableWithProps(table, mergedProps.build());
  }

  private Table loadIcebergTable(ObjectPath tablePath) throws TableNotExistException {
    try {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Remove the reserved keys from the Iceberg table properties: ALTER TABLE t UNSET TBLPROPERTIES ('connector') (or the src-catalog key), or remove via icebergCatalog table.updateProperties().
  2. Recreate the table without the reserved keys and reload data.
  3. Audit creation pipelines so Flink connector/src-catalog options are never persisted into Iceberg table properties.

Example fix

// before
table.updateProperties().set("connector", "iceberg").commit();

// after
TableMetadata metadata = ((HasTableOperations) table).operations().current();
table.updateProperties().remove("connector").commit(); // reserved key must not be stored
Defensive patterns

Strategy: validation

Validate before calling

Map<String, String> props = table.properties();
if (props.containsKey("connector") || props.containsKey("src-catalog")) {
  throw new IllegalStateException("reserved Flink keys present in Iceberg table properties");
}

Try / catch

try {
  CatalogTable t = catalog.getTable(tablePath);
} catch (IllegalArgumentException e) {
  // strip reserved keys via table update and retry
}

Prevention

When it happens

Trigger: Reading a table (getTable, or SELECT via the catalog) whose Iceberg table properties were manually set to include 'connector' or the src-catalog property key — typically because a previous CREATE TABLE LIKE artifact was persisted or someone added the key with ALTER TABLE TPROPERTIES.

Common situations: Manually copying properties from a Flink-side dynamic table back into the Iceberg table; custom ingestion jobs that persist Flink connector options; restoring table snapshots that contain stale reserved keys.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/7031fd5702e6efb6. Report an issue: GitHub.