apache/iceberg · error · UnsupportedOperationException
Expected value to be timestamp:
Error message
Expected value to be timestamp:
What it means
Bind-time type validation in HoursFunction.doBind: the argument to system.hours is neither TimestampType nor TimestampNTZType — the hour transform only applies to timestamp-like inputs. The appended value is the actual type; binding fails before execution.
Solutions
- Cast a date/string to timestamp: system.hours(CAST(d AS TIMESTAMP)) or system.hours(to_timestamp(s))
- Use system.days or system.months for date-only columns instead of hours
- Convert epoch values: system.hours(timestamp_millis(col))
Example fix
// before SELECT * FROM t WHERE system.hours(event_date) >= 100; -- DATE // after SELECT * FROM t WHERE system.hours(CAST(event_date AS TIMESTAMP)) >= 100;
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(value.dataType() instanceof TimestampType) && !(value.dataType() instanceof TimestampNTZType)) {
throw new IllegalArgumentException("hours() requires timestamp, got: " + value.dataType());
} Type guard
boolean isTimestampLike(DataType t) {
return t instanceof TimestampType || t instanceof TimestampNTZType;
} Try / catch
try {
bound = hoursFn.doBind(valueType);
} catch (UnsupportedOperationException e) {
throw new IllegalArgumentException("Cast the expression to TIMESTAMP", e);
} Prevention
- Use days()/months() for DATE columns instead of hours()
- Cast date or string values to timestamp before hours()
- Convert epoch values via timestamp_millis/timestamp_micros
When it happens
Trigger: Calling system.hours(<expr>) with a date, string, or numeric expression instead of a timestamp, e.g. system.hours(d) where d is DATE.
Common situations: Applying hours() to date partition columns; passing string timestamps without casting; applying hours() to epoch-millis bigints.
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 date or 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/1885858e70c1daee.
Report an issue: GitHub.
Appendix: source
Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/functions/HoursFunction.java:46
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.TimestampNTZType;
import org.apache.spark.sql.types.TimestampType;
/**
* A Spark function implementation for the Iceberg hour transform.
*
* <p>Example usage: {@code SELECT system.hours('source_col')}.
*/
public class HoursFunction extends UnaryUnboundFunction {
@Override
protected BoundFunction doBind(DataType valueType) {
if (valueType instanceof TimestampType) {
return new TimestampToHoursFunction();
} else if (valueType instanceof TimestampNTZType) {
return new TimestampNtzToHoursFunction();
} else {
throw new UnsupportedOperationException(
"Expected value to be timestamp: " + valueType.catalogString());
}
}
@Override
public String description() {
return name()
+ "(col) - Call Iceberg's hour transform\n"
+ " col :: source column (must be timestamp)";
}
@Override
public String name() {
return "hours";
}
public abstract static class BaseToHourFunction extends BaseScalarFunction<Integer>
implements ReducibleFunction<Integer, Integer> {View on GitHub (pinned to 86d9c8fc54)