apache/iceberg · warning

: Fallback to use 'none' distribution mode, because there…

Error message

{}: Fallback to use 'none' distribution mode, because there are no equality fields set and table is unpartitioned

What it means

In the dynamic Iceberg sink's HashKeyGenerator, a table requesting HASH distribution with no equality fields and an unpartitioned spec has no key to hash on. The generator warns and falls back to a table-level key selector (keying by table name with limited parallelism) instead of a partition key selector.

Solutions

  1. Declare equality fields on the dynamic records / target table so hash distribution has keys.
  2. Add partitioning to the table if hash-by-partition was intended.
  3. Accept the fallback — records are keyed per table, which serializes writes to that table (reduced parallelism).

Example fix

// before
dynamicRecord.withEqualityFields(Collections.emptyList()) // unpartitioned table, HASH mode
// after
dynamicRecord.withEqualityFields(Arrays.asList("id"))
Defensive patterns

Strategy: validation

Validate before calling

if (distMode == HASH && spec.isUnpartitioned() && equalityFields.isEmpty()) {
  LOG.warn("Table {} will fall back to per-table keying; declare equality fields or partitioning", tableName);
}

Prevention

When it happens

Trigger: A DynamicRecord targeting an unpartitioned table with empty equality fields whose requested distribution mode resolves to HASH.

Common situations: Sending upsert-style records to an unpartitioned table without declaring equality fields; table metadata lacking identifier fields; copy-pasted job config assuming partitioned tables.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/sink/dynamic/HashKeyGenerator.java:140

      int writeParallelism) {
    LOG.debug(
        "Creating new KeySelector for table '{}' with distribution mode '{}'", tableName, mode);
    switch (mode) {
      case NONE:
        if (equalityFields.isEmpty()) {
          return tableKeySelector(tableName, writeParallelism, maxWriteParallelism);
        } else {
          LOG.info(
              "{}: Distribute rows by equality fields, because there are equality fields set",
              tableName);
          return equalityFieldKeySelector(
              tableName, schema, equalityFields, writeParallelism, maxWriteParallelism);
        }

      case HASH:
        if (equalityFields.isEmpty()) {
          if (spec.isUnpartitioned()) {
            LOG.warn(
                "{}: Fallback to use 'none' distribution mode, because there are no equality fields set "
                    + "and table is unpartitioned",
                tableName);
            return tableKeySelector(tableName, writeParallelism, maxWriteParallelism);
          } else {
            return partitionKeySelector(
                tableName, schema, spec, writeParallelism, maxWriteParallelism);
          }
        } else {
          if (spec.isUnpartitioned()) {
            LOG.info(
                "{}: Distribute rows by equality fields, because there are equality fields set "
                    + "and table is unpartitioned",
                tableName);
            return equalityFieldKeySelector(
                tableName, schema, equalityFields, writeParallelism, maxWriteParallelism);
          } else {
            for (PartitionField partitionField : spec.fields()) {

View on GitHub (pinned to 86d9c8fc54)