{"record":{"id":"e7be5a5c270bf167","repo":"apache/iceberg","slug":"expected-value-to-be-date-or-timestamp-valuetyp-e7be5a","errorCode":null,"errorMessage":"Expected value to be date or timestamp: ${valueType.catalogString()}","messagePattern":"Expected value to be date or timestamp: (.+?)","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/functions/MonthsFunction.java","lineNumber":46,"sourceCode":"import org.apache.spark.sql.types.TimestampType;\n\n/**\n * A Spark function implementation for the Iceberg month transform.\n *\n * <p>Example usage: {@code SELECT system.months('source_col')}.\n */\npublic class MonthsFunction extends UnaryUnboundFunction {\n\n  @Override\n  protected BoundFunction doBind(DataType valueType) {\n    if (valueType instanceof DateType) {\n      return new DateToMonthsFunction();\n    } else if (valueType instanceof TimestampType) {\n      return new TimestampToMonthsFunction();\n    } else if (valueType instanceof TimestampNTZType) {\n      return new TimestampNtzToMonthsFunction();\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 month transform\\n\"\n        + \"  col :: source column (must be date or timestamp)\";\n  }\n\n  @Override\n  public String name() {\n    return \"months\";\n  }\n\n  private abstract static class BaseToMonthsFunction 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/MonthsFunction.java#L28-L64","documentation":"Iceberg's months(x) Spark transform function only accepts date, timestamp, or timestamp_ntz inputs. Binding any other value type (string, numeric, etc.) throws this UnsupportedOperationException, appending the offending type's catalogString. Thrown during query analysis via doBind.","triggerScenarios":"Calling months(value) where value is a StringType date ('2024-01-01'), a numeric epoch column, or any non-temporal type, e.g. months(month_str).","commonSituations":"Monthly partitioning over string-typed date columns; passing bigint epochs; CREATE TABLE partition specs referencing non-temporal columns.","solutions":["Cast to a temporal type: months(CAST(month_str AS DATE)).","Use to_date/to_timestamp before months(), e.g. months(to_date(str_col, 'yyyy-MM')).","Convert epoch numbers with timestamp_millis/seconds_to_timestamp before months().","Correct the schema or partition column to a date/timestamp type."],"exampleFix":"// before\nSELECT months(month_str) FROM t  -- month_str is STRING\n// after\nSELECT months(to_date(month_str, 'yyyy-MM')) FROM t","handlingStrategy":"validation","validationCode":"// Spark Scala\nval dt = df.schema(\"value_col\").dataType\nrequire(dt == org.apache.spark.sql.types.DateType || dt.typeName.startsWith(\"timestamp\"),\n  s\"months() requires DATE or TIMESTAMP, got: ${dt.catalogString}\")","typeGuard":"def isTemporalType(dt: org.apache.spark.sql.types.DataType): Boolean =\n  dt == org.apache.spark.sql.types.DateType ||\n  dt.isInstanceOf[org.apache.spark.sql.types.TimestampType] ||\n  dt.typeName == \"timestamp_ntz\"","tryCatchPattern":"try {\n  df.select(expr(\"months(ts_col)\"))\n} catch {\n  case e: UnsupportedOperationException if e.getMessage.startsWith(\"Expected value to be date or timestamp\") =>\n    throw new IllegalArgumentException(\"months() needs DATE/TIMESTAMP; cast with to_date/to_timestamp first\", e)\n}","preventionTips":["Convert string date columns with to_date()/to_timestamp() before months()","Convert epoch numerics with timestamp_millis() before months()","In monthly partition specs, confirm the column is DATE/TIMESTAMP in the schema","Add schema assertions in ETL jobs before writing with monthly partitions"],"tags":["spark","sql-function","type-mismatch","temporal"],"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"}