{"record":{"id":"887b7863a9513f2d","repo":"apache/iceberg","slug":"expected-value-to-be-date-or-timestamp-valuetyp","errorCode":null,"errorMessage":"Expected value to be date or timestamp: ${valueType.catalogString()}","messagePattern":"Expected value to be date or timestamp: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/functions/DaysFunction.java","lineNumber":46,"sourceCode":"import org.apache.spark.sql.types.TimestampType;\n\n/**\n * A Spark function implementation for the Iceberg day transform.\n *\n * <p>Example usage: {@code SELECT system.days('source_col')}.\n */\npublic class DaysFunction extends UnaryUnboundFunction {\n\n  @Override\n  protected BoundFunction doBind(DataType valueType) {\n    if (valueType instanceof DateType) {\n      return new DateToDaysFunction();\n    } else if (valueType instanceof TimestampType) {\n      return new TimestampToDaysFunction();\n    } else if (valueType instanceof TimestampNTZType) {\n      return new TimestampNtzToDaysFunction();\n    } else {\n      throw new UnsupportedOperationException(\n          \"Expected value to be date or timestamp: \" + valueType.catalogString());\n    }\n  }\n\n  @Override\n  public String description() {\n    return name()\n        + \"(col) - Call Iceberg's day transform\\n\"\n        + \"  col :: source column (must be date or timestamp)\";\n  }\n\n  @Override\n  public String name() {\n    return \"days\";\n  }\n\n  private abstract static class BaseToDaysFunction extends BaseScalarFunction<Integer> {\n    @Override","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/functions/DaysFunction.java#L28-L64","documentation":"The days() SQL catalog function (year/month/day family — here DaysFunction) only accepts date or timestamp (incl. timestamp_ntz) values. Binding with any other value type throws UnsupportedOperationException including the actual type.","triggerScenarios":"Calling system.days(ts) where ts is a string, long epoch, or other non-date/timestamp type.","commonSituations":"Passing string datetime literals ('2024-01-01') without a cast; passing epoch millis as bigint; mistakenly passing a date-typed column to hours() variant or vice versa.","solutions":["Cast the value: system.days(CAST('2024-01-01' AS DATE)) or system.days(CAST(ts_str AS TIMESTAMP))","Convert epoch numbers to a timestamp first (timestamp_millis(col)) before applying days()","Use the matching function for the type (e.g. days for date/timestamp, not for strings)"],"exampleFix":"// before\nspark.sql(\"SELECT system.days('2024-01-01')\")\n// after\nspark.sql(\"SELECT system.days(CAST('2024-01-01' AS DATE))\")","handlingStrategy":"type-guard","validationCode":"-- Cast non-temporal inputs first\nSELECT system.days(CAST(ts_str AS TIMESTAMP)) FROM tbl;","typeGuard":"boolean daysOk(DataType t) { return t instanceof DateType || t instanceof TimestampType || t instanceof TimestampNTZType; }","tryCatchPattern":null,"preventionTips":["Cast string datetimes explicitly before temporal transform functions","Convert epoch numbers with timestamp_millis/timestamp_micros first","Check column types with DESCRIBE before writing SQL"],"tags":["spark","sql-functions","temporal","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}