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 HashKeyGenerator (dynamic sink), when the requested write uses HASH distribution but has no equality fields and the table is unpartitioned, there is no meaningful key to distribute by, so it warns and falls back to a table-level key selector ('none' mode), bucketing only by table name up to the write parallelism.

Solutions

  1. Partition the target tables so a partitionKeySelector can be used
  2. Accept the table-level fallback if append throughput is fine and files are adequately sized
  3. Set the tables' write.distribution-mode to 'none' explicitly to make the fallback intentional and silence intent ambiguity

Example fix

// before
// table unpartitioned, no equality fields, distribution-mode=hash
// after
ALTER TABLE t SET TBLPROPERTIES ('write.distribution-mode'='none');
Defensive patterns

Strategy: validation

Validate before calling

if (spec.isUnpartitioned() && equalityFields.isEmpty() && "hash".equals(distributionMode)) {
  // expect 'none' fallback; adjust table or mode
}

Prevention

When it happens

Trigger: A DynamicRecord targeting an unpartitioned table with no equality fields arrives while the distribution mode resolves to HASH in HashKeyGenerator.getKeySelector.

Common situations: Dynamic Iceberg sink jobs writing append-only data to unpartitioned tables; per-table metadata (distribution-mode=hash) set without partition keys; uneven/small-file output across writers.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at flink/v2.3/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)