apache/iceberg · error · java.lang.UnsupportedOperationException
Expected value to be date or timestamp: ${valueType.catalogS
Error message
Expected value to be date or timestamp: ${valueType.catalogString()} What it means
Iceberg's months(x) Spark transform function only accepts date, timestamp, or timestamp_ntz inputs. Binding any other value type (string, numeric, etc.) throws this UnsupportedOperationException, appending the offending type's catalogString. Thrown during query analysis via doBind.
Source
Thrown at spark/v4.2/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)
Solutions
- Cast to a temporal type: months(CAST(month_str AS DATE)).
- Use to_date/to_timestamp before months(), e.g. months(to_date(str_col, 'yyyy-MM')).
- Convert epoch numbers with timestamp_millis/seconds_to_timestamp before months().
- Correct the schema or partition column to a date/timestamp type.
Example fix
// before SELECT months(month_str) FROM t -- month_str is STRING // after SELECT months(to_date(month_str, 'yyyy-MM')) FROM t
Defensive patterns
Strategy: validation
Validate before calling
// Spark Scala
val dt = df.schema("value_col").dataType
require(dt == org.apache.spark.sql.types.DateType || dt.typeName.startsWith("timestamp"),
s"months() requires DATE or TIMESTAMP, got: ${dt.catalogString}") Type guard
def isTemporalType(dt: org.apache.spark.sql.types.DataType): Boolean = dt == org.apache.spark.sql.types.DateType || dt.isInstanceOf[org.apache.spark.sql.types.TimestampType] || dt.typeName == "timestamp_ntz"
Try / catch
try {
df.select(expr("months(ts_col)"))
} catch {
case e: UnsupportedOperationException if e.getMessage.startsWith("Expected value to be date or timestamp") =>
throw new IllegalArgumentException("months() needs DATE/TIMESTAMP; cast with to_date/to_timestamp first", e)
} Prevention
- Convert string date columns with to_date()/to_timestamp() before months()
- Convert epoch numerics with timestamp_millis() before months()
- In monthly partition specs, confirm the column is DATE/TIMESTAMP in the schema
- Add schema assertions in ETL jobs before writing with monthly partitions
When it happens
Trigger: Calling months(value) where value is a StringType date ('2024-01-01'), a numeric epoch column, or any non-temporal type, e.g. months(month_str).
Common situations: Monthly partitioning over string-typed date columns; passing bigint epochs; CREATE TABLE partition specs referencing non-temporal columns.
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 value to be date or timestamp: ${valueType.catalogS
- Expected value to be date or timestamp: ${valueType.catalogS
- Expected value to be timestamp: ${valueType.catalogString()}
- Expected value to be date or timestamp: ${valueType.catalogS
- Expected value to be timestamp: ${valueType.catalogString()}
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/e7be5a5c270bf167.
Report an issue: GitHub.