{"record":{"id":"5509622b20caa15f","repo":"apache/iceberg","slug":"expected-value-to-be-date-or-timestamp-valuetyp-550962","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/v4.0/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/v4.0/spark/src/main/java/org/apache/iceberg/spark/functions/YearsFunction.java#L28-L64","documentation":"YearsFunction is a Spark Iceberg catalog function (years()) that only accepts DATE or TIMESTAMP/TIMESTAMP_NTZ input. During binding, the given input type is checked; any other type (e.g. numeric or string) is rejected because converting an arbitrary value to a year-partition value is undefined. The type's catalogString is appended to help identify the offending type.","triggerScenarios":"Calling SELECT years(col) in Spark SQL (or referencing the years() function) where col is not a date or timestamp — e.g. a bigint epoch column, a string 'yyyy-MM-dd', or an int year.","commonSituations":"Passing an epoch-millis BIGINT column to years() instead of casting to timestamp first; a table column typed as string because source data was ingested untyped; confusion with Spark's built-in year() which accepts date/timestamp only anyway.","solutions":["Cast the column to date or timestamp before applying years(): years(cast(epoch_col as timestamp)).","Parse string columns with to_date()/to_timestamp() before passing to years().","Verify the column's actual type with DESCRIBE TABLE and fix the ingestion schema.","If you just want the calendar year as an int, use Spark's built-in year(col) function instead of the Iceberg years() transform."],"exampleFix":"// before\nSELECT years(epoch_millis) FROM t;\n// after\nSELECT years(cast(epoch_millis / 1000 as timestamp)) FROM t;","handlingStrategy":"validation","validationCode":"if (!(col.dataType() instanceof DateType) && !(col.dataType() instanceof TimestampType) && !(col.dataType() instanceof TimestampNTZType)) { throw new IllegalArgumentException(\"years() requires date/timestamp: \" + col.dataType().catalogString()); }","typeGuard":"boolean isTemporal(DataType t) { return t instanceof DateType || t instanceof TimestampType || t instanceof TimestampNTZType; }","tryCatchPattern":null,"preventionTips":["Check the column type with DESCRIBE TABLE before using Iceberg transforms.","Cast epoch/bigint columns to timestamp explicitly.","Use Spark's built-in year() when you need an int, not a partition transform."],"tags":["spark","sql-function","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"}