{"record":{"id":"1e90421fe145eda4","repo":"apache/iceberg","slug":"month-transform-is-not-supported","errorCode":null,"errorMessage":"Month transform is not supported","messagePattern":"Month transform is not supported","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/org/apache/iceberg/transforms/PartitionSpecVisitor.java","lineNumber":65,"sourceCode":"\n  default T truncate(String sourceName, int sourceId, int width) {\n    throw new UnsupportedOperationException(\"Truncate transform is not supported\");\n  }\n\n  default T year(int fieldId, String sourceName, int sourceId) {\n    return year(sourceName, sourceId);\n  }\n\n  default T year(String sourceName, int sourceId) {\n    throw new UnsupportedOperationException(\"Year transform is not supported\");\n  }\n\n  default T month(int fieldId, String sourceName, int sourceId) {\n    return month(sourceName, sourceId);\n  }\n\n  default T month(String sourceName, int sourceId) {\n    throw new UnsupportedOperationException(\"Month transform is not supported\");\n  }\n\n  default T day(int fieldId, String sourceName, int sourceId) {\n    return day(sourceName, sourceId);\n  }\n\n  default T day(String sourceName, int sourceId) {\n    throw new UnsupportedOperationException(\"Day transform is not supported\");\n  }\n\n  default T hour(int fieldId, String sourceName, int sourceId) {\n    return hour(sourceName, sourceId);\n  }\n\n  default T hour(String sourceName, int sourceId) {\n    throw new UnsupportedOperationException(\"Hour transform is not supported\");\n  }\n","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/api/src/main/java/org/apache/iceberg/transforms/PartitionSpecVisitor.java#L47-L83","documentation":"PartitionSpecVisitor's default month() methods throw UnsupportedOperationException to signal that the concrete visitor does not handle partition fields using the month temporal transform. When PartitionSpecVisitor.visit encounters a field transformed by Dates.MONTH, Timestamps.MICROS_TO_MONTH/NANOS_TO_MONTH, or an instance of Months, it dispatches to month(); an implementation that skipped this override hits the throwing default. This fail-fast prevents silently mis-translating partition specs.","triggerScenarios":"PartitionSpecVisitor.visit on a table partitioned with month(date_col) or month(ts_col) where the visitor implementation lacks a month(int, String, int) or month(String, int) override.","commonSituations":"Custom catalog-integration visitors (Hive metastore, JDBC, Nessie translators) that handle identity/bucket/truncate but not temporal transforms; applying a visitor written for a different table to one partitioned by month.","solutions":["Override month(int fieldId, String sourceName, int sourceId) in your visitor to translate the month transform correctly","Pre-validate the partition spec's partitionType() to detect month transforms before invoking the visitor","If month partitioning is genuinely unsupported in your target, override month() to raise a clear domain error or skip the field explicitly"],"exampleFix":"// before\n@Override\npublic String identity(int fieldId, String sourceName, int sourceId) { return sourceName; }\n// month transform falls through to throwing default\n// after\n@Override\npublic String month(int fieldId, String sourceName, int sourceId) {\n  return \"months(\" + sourceName + \")\";\n}","handlingStrategy":"validation","validationCode":"boolean hasMonthTransform(PartitionSpec spec) {\n  return spec.fields().stream().anyMatch(f -> f.transform() instanceof Months\n      || f.transform() == Dates.MONTH || f.transform() == Timestamps.MICROS_TO_MONTH);\n}\n// run before visit(); reject or add a month() override first","typeGuard":"if (field.transform() instanceof Months) {\n  throw new IllegalStateException(\"Visitor does not support month transform: \" + field);\n}","tryCatchPattern":"try {\n  PartitionSpecVisitor.visit(spec, visitor);\n} catch (UnsupportedOperationException e) {\n  LOG.error(\"Visitor missing month-transform support for spec {}\", spec, e);\n  throw e;\n}","preventionTips":["Enumerate spec.partitionType().fields() and assert each transform string is one your visitor implements","Include month-partitioned tables in visitor unit tests","When copying specs between catalogs, verify target support for temporal transforms first"],"tags":["java","partitioning","visitor-pattern","unsupported-transform"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}