apache/iceberg · error · UnsupportedOperationException

Expected value to be date or timestamp: ${valueType.catalogS

Error message

Expected value to be date or timestamp: ${valueType.catalogString()}

What it means

The months() SQL catalog function only accepts date or timestamp (incl. timestamp_ntz) values. Binding with any other value type throws UnsupportedOperationException including the actual type via catalogString().

Source

Thrown at spark/v3.5/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)

Solutions

  1. Cast the value: system.months(CAST(ts_str AS TIMESTAMP)) or system.months(CAST(d AS DATE))
  2. Convert numeric epochs with timestamp_millis()/timestamp_micros() before months()
  3. Use the months() only for temporal columns; otherwise use month() extraction functions

Example fix

// before
spark.sql("SELECT system.months('2024-03-15')")
// after
spark.sql("SELECT system.months(CAST('2024-03-15' AS DATE))")
Defensive patterns

Strategy: type-guard

Validate before calling

// months() accepts date/timestamp only
boolean monthsOk(DataType t) { return t instanceof DateType || t instanceof TimestampType || t instanceof TimestampNTZType; }

Type guard

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

Prevention

When it happens

Trigger: Calling system.months(value) where value is a string, long, decimal, or other non-date/timestamp type.

Common situations: Passing string dates without CAST; passing epoch values; passing an int year-month number expecting month extraction.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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