apache/iceberg · error · UnsupportedOperationException

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

Error message

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

What it means

The hours() SQL catalog function accepts only timestamp (or timestamp_ntz) values since hour extraction is defined on instants. Any other type, including DATE, fails bind with UnsupportedOperationException naming the actual type.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/functions/HoursFunction.java:43

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 static class TimestampToHoursFunction extends BaseScalarFunction<Integer> {
    // magic method used in codegen

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Cast date to timestamp if an implicit midnight hour is intended: system.hours(CAST(d AS TIMESTAMP))
  2. Use system.days() for DATE columns instead
  3. Cast string values to TIMESTAMP before calling hours()

Example fix

// before
spark.sql("SELECT system.hours(event_date) FROM tbl") -- event_date is DATE
// after
spark.sql("SELECT system.days(event_date) FROM tbl")
Defensive patterns

Strategy: type-guard

Validate before calling

// hours() requires timestamp-like types
boolean hoursOk(DataType t) { return t instanceof TimestampType || t instanceof TimestampNTZType; }

Type guard

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

Prevention

When it happens

Trigger: Calling system.hours(col) where col is DATE, string, or another non-timestamp type.

Common situations: Passing a date column to hours() (a date has no hour component); passing string timestamps without casting; mixing up days()/hours() functions.

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/2ba2502b8330dbf2. Report an issue: GitHub.