apache/iceberg · error · UnsupportedOperationException
Expected value to be date or timestamp
Error message
Expected value to be date or timestamp: ${valueType.catalogString()} What it means
Iceberg's months() transform function binds its single argument at planning time. Only DATE, TIMESTAMP, and TIMESTAMP_NTZ support month granularity; any other type throws UnsupportedOperationException that echoes the offending type.
Solutions
- Cast the column: months(cast(ts_str AS TIMESTAMP)).
- For epoch seconds: months(timestamp_seconds(epoch_col)).
- Verify the column type with typeof(col) before applying the transform.
Example fix
// before SELECT iceberg.months(order_ts_str) FROM t; // after SELECT iceberg.months(CAST(order_ts_str AS TIMESTAMP)) FROM t;
Defensive patterns
Strategy: type-guard
Validate before calling
require(Seq(DateType, TimestampType, TimestampNTZType).exists(_.acceptsType(col.dataType)),
s"months() requires date/timestamp, got ${col.dataType}") Type guard
def isTemporalForMonths(t: DataType): Boolean = t == DateType || t == TimestampType || t == TimestampNTZType
Prevention
- Validate column types after schema migrations — a timestamp changed to string will break months()
- Cast string timestamps explicitly before temporal transforms
When it happens
Trigger: Calling iceberg.months(col) where col is STRING, INT, BIGINT, or any non-temporal type — e.g. months(order_ts_str).
Common situations: Monthly partitioning attempts on string-typed timestamps; passing epoch BIGINT columns; type drift after schema migration changed a timestamp column to string.
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
- Expected column to be date, tinyint, smallint, int, bigint…
- Expected truncation col to be tinyint, shortint, int…
- Expected value to be date or timestamp
- Expected value to be timestamp
- Cannot bind: does not accept arguments
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/94d6984800f69e0e.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.0/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> {
@OverrideView on GitHub (pinned to 86d9c8fc54)