apache/iceberg · warning

Unsupported runtime filter

Error message

Unsupported runtime filter {}

What it means

SparkCopyOnWriteScan implements runtime filtering for copy-on-write deletes; when filter() receives a predicate that SparkV2Filters cannot convert to an Iceberg expression, it warns and ignores that predicate. Other convertible filters in the same call still apply, and scan correctness is unaffected.

Solutions

  1. No correctness action needed; the filter is simply not used to prune delete files.
  2. Confirm which predicate was unsupported and whether a supported equivalent exists.
  3. Upgrade the Iceberg Spark runtime for broader SparkV2Filters coverage.
Defensive patterns

Strategy: fallback

Type guard

if (SparkV2Filters.convert(predicate) == null) { /* unsupported for CoW delete planning */ }

Prevention

When it happens

Trigger: Spark passes a runtime predicate with an unsupported function/type to SparkCopyOnWriteScan.filter during delete-file planning.

Common situations: Newer Spark runtime filter functions not yet mapped in SparkV2Filters; custom predicates applied during MERGE/DELETE planning on CoW tables.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/source/SparkCopyOnWriteScan.java:141

        // so filter files only if it is beneficial
        if (filteredLocations == null || fileLocations.size() < filteredLocations.size()) {
          this.filteredLocations = fileLocations;
          List<FileScanTask> filteredTasks =
              tasks().stream()
                  .filter(file -> fileLocations.contains(file.file().location()))
                  .collect(Collectors.toList());

          LOG.info(
              "{} of {} task(s) for table {} matched runtime file filter with {} location(s)",
              filteredTasks.size(),
              tasks().size(),
              table().name(),
              fileLocations.size());

          resetTasks(filteredTasks);
        }
      } else {
        LOG.warn("Unsupported runtime filter {}", predicate);
      }
    }
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }

    if (o == null || getClass() != o.getClass()) {
      return false;
    }

    SparkCopyOnWriteScan that = (SparkCopyOnWriteScan) o;
    return table().name().equals(that.table().name())
        && readSchema().equals(that.readSchema()) // compare Spark schemas to ignore field ids
        && filterExpressions().toString().equals(that.filterExpressions().toString())

View on GitHub (pinned to 86d9c8fc54)