{"record":{"id":"65a237cedb1573ec","repo":"apache/iceberg","slug":"expected-value-to-be-date-or-timestamp-valuetyp-65a237","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.2/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.2/spark/src/main/java/org/apache/iceberg/spark/functions/YearsFunction.java#L28-L64","documentation":"YearsFunction is a Spark Iceberg vectorized function that converts date/timestamp values to a year count (Iceberg 'years' transform). Binding validates the input Spark DataType; when the argument is not DateType, TimestampType, or TimestampNTZType, binding fails with this UnsupportedOperationException listing the offending type's catalog string.","triggerScenarios":"Calling years(col) in Spark SQL or DataFrame API with an input column whose type is not a date or timestamp — e.g. a string, int, or decimal column passed to the years() function.","commonSituations":"Passing a string that looks like a date ('2024-01-01') without casting; using years() on a numeric epoch column; schema drift after upstream changes made the column a string.","solutions":["Cast the input column to date or timestamp before calling years(), e.g. years(to_date(col)) or years(col.cast(\"timestamp\")).","If the source is a string, use to_date or to_timestamp with an explicit format string.","Verify the column's actual Spark type with df.printSchema() and fix the upstream schema if it drifted."],"exampleFix":"// before\nSELECT years(event_date_str) FROM events;\n// after\nSELECT years(to_date(event_date_str, 'yyyy-MM-dd')) FROM events;","handlingStrategy":"validation","validationCode":"val allowed = Seq(\"date\", \"timestamp\", \"timestamp_ntz\")\nrequire(allowed.contains(df.schema(\"event_ts\").dataType.typeName), \"years() needs date/timestamp column\")","typeGuard":"def isDateOrTimestamp(dt: org.apache.spark.sql.types.DataType): Boolean =\n  dt match {\n    case _: org.apache.spark.sql.types.DateType => true\n    case _: org.apache.spark.sql.types.TimestampType => true\n    case _: org.apache.spark.sql.types.TimestampNTZType => true\n    case _ => false\n  }","tryCatchPattern":null,"preventionTips":["Check df.printSchema() before applying transform functions","Cast string dates explicitly with to_date/to_timestamp","Guard shared SQL templates against schema drift"],"tags":["spark","sql","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"}