apache/iceberg · error · UnsupportedOperationException

Expected value to be date or timestamp:

Error message

Expected value to be date or timestamp: 

What it means

Bind-time type validation in MonthsFunction.doBind: the argument to system.months is not a date or timestamp type (DateType, TimestampType, TimestampNTZType are the accepted kinds). The appended value is the offending type; the function cannot be bound for it.

Solutions

  1. Cast to date/timestamp: system.months(CAST(col AS DATE)) or system.months(to_date('2024-01-01'))
  2. Use years() or days() where appropriate; ensure the partition transform column is temporal
  3. Convert epoch numbers: system.months(timestamp_millis(col))

Example fix

// before
SELECT * FROM t WHERE system.months(dt_str) = 650;
// after
SELECT * FROM t WHERE system.months(CAST(dt_str AS DATE)) = 650;
Defensive patterns

Strategy: validation

Validate before calling

if (!(value.dataType() instanceof DateType) && !(value.dataType() instanceof TimestampType) && !(value.dataType() instanceof TimestampNTZType)) {
  throw new IllegalArgumentException("months() requires date or timestamp, got: " + value.dataType());
}

Type guard

boolean temporal(DataType t) {
  return t instanceof DateType || t instanceof TimestampType || t instanceof TimestampNTZType;
}

Try / catch

try {
  bound = monthsFn.doBind(valueType);
} catch (UnsupportedOperationException e) {
  throw new IllegalArgumentException("Cast the expression to DATE or TIMESTAMP", e);
}

Prevention

When it happens

Trigger: Calling system.months(<expr>) with a string, numeric, or other non-temporal expression, e.g. system.months('2024-01-01') or system.months(id).

Common situations: Passing date strings instead of literals; applying months() to bigint epoch columns; partition predicates comparing months() with raw strings.

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/fba91e0111726eab. Report an issue: GitHub.

Appendix: source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/functions/MonthsFunction.java:46

import org.apache.spark.sql.types.TimestampType;

/**
 * A Spark function implementation for the Iceberg month transform.
 *
 * <p>Example usage: {@code SELECT system.months('source_col')}.
 */
public class MonthsFunction extends UnaryUnboundFunction {

  @Override
  protected BoundFunction doBind(DataType valueType) {
    if (valueType instanceof DateType) {
      return new DateToMonthsFunction();
    } else if (valueType instanceof TimestampType) {
      return new TimestampToMonthsFunction();
    } else if (valueType instanceof TimestampNTZType) {
      return new TimestampNtzToMonthsFunction();
    } else {
      throw new UnsupportedOperationException(
          "Expected value to be date or timestamp: " + valueType.catalogString());
    }
  }

  @Override
  public String description() {
    return name()
        + "(col) - Call Iceberg's month transform\n"
        + "  col :: source column (must be date or timestamp)";
  }

  @Override
  public String name() {
    return "months";
  }

  private abstract static class BaseToMonthsFunction extends BaseScalarFunction<Integer> {
    @Override

View on GitHub (pinned to 86d9c8fc54)