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 DaysFunction.doBind: the argument to system.days is neither DateType, TimestampType nor TimestampNTZType (the three temporal kinds the day transform accepts). The appended value is the offending type; the failure occurs when Spark binds the function, before any row is evaluated.
Solutions
- Cast to date/timestamp first: system.days(CAST(col AS DATE)) or system.days(CAST('2024-01-01' AS DATE))
- Use to_date/to_timestamp to convert strings: system.days(to_date('2024-01-01'))
- For epoch-second bigint columns, convert: system.days(timestamp_millis(col * 1000))
Example fix
// before SELECT * FROM t WHERE system.days(ts_col_string) = ...; -- string // after SELECT * FROM t WHERE system.days(CAST(ts_col_string AS TIMESTAMP)) = ...;
Defensive patterns
Strategy: validation
Validate before calling
if (!(value.dataType() instanceof DateType) && !(value.dataType() instanceof TimestampType) && !(value.dataType() instanceof TimestampNTZType)) {
throw new IllegalArgumentException("days() 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 = daysFn.doBind(valueType);
} catch (UnsupportedOperationException e) {
throw new IllegalArgumentException("Cast the expression to DATE or TIMESTAMP", e);
} Prevention
- Cast strings/numbers to date/timestamp before temporal transforms
- Never pass raw epoch bigints to days()/hours()/months()
- Use to_date/to_timestamp for string values in partition predicates
When it happens
Trigger: Calling system.days(<expr>) where expr is a string, long, or other non-temporal type, e.g. system.days('2024-01-01') or system.days(id).
Common situations: Passing date strings instead of date literals; applying days() to bigint epoch columns; comparing partition columns with uncast values in SQL predicates.
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
- Expected value to be date or timestamp:
- Expected value to be timestamp:
- Expected column to be date, tinyint, smallint, int, bigint…
- Expected number of buckets to be tinyint, shortint or int
- Expected number of buckets to be tinyint, shortint or int
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/74a753a22b408701.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/functions/DaysFunction.java:48
import org.apache.spark.sql.types.TimestampType;
/**
* A Spark function implementation for the Iceberg day transform.
*
* <p>Example usage: {@code SELECT system.days('source_col')}.
*/
public class DaysFunction extends UnaryUnboundFunction {
@Override
protected BoundFunction doBind(DataType valueType) {
if (valueType instanceof DateType) {
return new DateToDaysFunction();
} else if (valueType instanceof TimestampType) {
return new TimestampToDaysFunction();
} else if (valueType instanceof TimestampNTZType) {
return new TimestampNtzToDaysFunction();
} else {
throw new UnsupportedOperationException(
"Expected value to be date or timestamp: " + valueType.catalogString());
}
}
@Override
public String description() {
return name()
+ "(col) - Call Iceberg's day transform\n"
+ " col :: source column (must be date or timestamp)";
}
@Override
public String name() {
return "days";
}
protected abstract static class BaseToDaysFunction extends BaseScalarFunction<Integer>
implements ReducibleFunction<Integer, Integer> {View on GitHub (pinned to 86d9c8fc54)