{"record":{"id":"8f8f9a118680aebf","repo":"apache/iceberg","slug":"expected-value-to-be-date-or-timestamp-valuetyp-8f8f9a","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/YearsFunction.java","lineNumber":46,"sourceCode":"import org.apache.spark.sql.types.TimestampType;\n\n/**\n * A Spark function implementation for the Iceberg year transform.\n *\n * <p>Example usage: {@code SELECT system.years('source_col')}.\n */\npublic class YearsFunction extends UnaryUnboundFunction {\n\n  @Override\n  protected BoundFunction doBind(DataType valueType) {\n    if (valueType instanceof DateType) {\n      return new DateToYearsFunction();\n    } else if (valueType instanceof TimestampType) {\n      return new TimestampToYearsFunction();\n    } else if (valueType instanceof TimestampNTZType) {\n      return new TimestampNtzToYearsFunction();\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 year transform\\n\"\n        + \"  col :: source column (must be date or timestamp)\";\n  }\n\n  @Override\n  public String name() {\n    return \"years\";\n  }\n\n  private abstract static class BaseToYearsFunction 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/YearsFunction.java#L28-L64","documentation":"Iceberg's `years` function binds only when the value is a date, timestamp, or timestamp_ntz. `doBind` in YearsFunction throws this UnsupportedOperationException, including the actual type via `catalogString()`, when given any other type, since converting to years-since-epoch is only defined for temporal types.","triggerScenarios":"Calling `years(col)` where col is int, bigint, string, decimal, etc., instead of DATE/TIMESTAMP/TIMESTAMP_NTZ.","commonSituations":"Passing epoch integers expecting conversion; passing string dates without CAST; schema evolution changed a column from date to string.","solutions":["Cast to a temporal type: `years(CAST(epoch_col AS TIMESTAMP))` or `years(to_date(str_col))`.","For epoch values, use timestamp_seconds first: `years(timestamp_seconds(epoch_col))`.","Verify the column type with DESCRIBE TABLE and fix the upstream schema."],"exampleFix":"// before\nspark.sql(\"SELECT years(ts_str) FROM t\")\n// after\nspark.sql(\"SELECT years(CAST(ts_str AS TIMESTAMP)) FROM t\")","handlingStrategy":"type-guard","validationCode":"DataType dt = df.schema().apply(\"col\").dataType();\nif (!(dt instanceof DateType || dt instanceof TimestampType || dt instanceof TimestampNTZType)) throw new IllegalArgumentException(\"years() requires a temporal column, got: \" + dt.simpleString());","typeGuard":"boolean isTemporal(DataType dt) { return dt instanceof DateType || dt instanceof TimestampType || dt instanceof TimestampNTZType; }","tryCatchPattern":"try { spark.sql(\"SELECT years(col) FROM t\"); } catch (UnsupportedOperationException e) { if (e.getMessage().startsWith(\"Expected value to be date or timestamp\")) { /* cast col to DATE/TIMESTAMP */ } throw e; }","preventionTips":["CAST string/epoch columns to DATE/TIMESTAMP before applying temporal functions.","Use timestamp_seconds() for epoch bigint columns.","Verify column types with DESCRIBE TABLE after schema changes."],"tags":["spark","sql-function","type-mismatch","temporal"],"backgroundTag":"incompatible-source-type","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"}