{"record":{"id":"83b54b549564e98a","repo":"apache/iceberg","slug":"invalid-unit-for-shredded-timestamp-unit","errorCode":null,"errorMessage":"Invalid unit for shredded timestamp: <unit>","messagePattern":"Invalid unit for shredded timestamp: <unit>","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"parquet/src/main/java/org/apache/iceberg/parquet/ParquetVariantUtil.java","lineNumber":111,"sourceCode":"\n  /**\n   * Convert a Parquet {@link TimestampLogicalTypeAnnotation} to the equivalent Variant {@link\n   * PhysicalType}.\n   *\n   * @param timestamp a Parquet {@link TimestampLogicalTypeAnnotation}\n   * @return a Variant {@link PhysicalType}\n   * @throws UnsupportedOperationException if the timestamp unit is not MICROS or NANOS\n   */\n  static PhysicalType convert(TimestampLogicalTypeAnnotation timestamp) {\n    switch (timestamp.getUnit()) {\n      case MICROS:\n        return timestamp.isAdjustedToUTC() ? PhysicalType.TIMESTAMPTZ : PhysicalType.TIMESTAMPNTZ;\n      case NANOS:\n        return timestamp.isAdjustedToUTC()\n            ? PhysicalType.TIMESTAMPTZ_NANOS\n            : PhysicalType.TIMESTAMPNTZ_NANOS;\n      default:\n        throw new UnsupportedOperationException(\n            \"Invalid unit for shredded timestamp: \" + timestamp.getUnit());\n    }\n  }\n\n  /**\n   * Serialize Variant metadata and value in a single concatenated buffer.\n   *\n   * @param metadata a {VariantMetadata}\n   * @param value a {VariantValue}\n   * @return a buffer containing the metadata and value serialized and concatenated\n   */\n  static ByteBuffer toByteBuffer(VariantMetadata metadata, VariantValue value) {\n    ByteBuffer buffer =\n        ByteBuffer.allocate(metadata.sizeInBytes() + value.sizeInBytes())\n            .order(ByteOrder.LITTLE_ENDIAN);\n    metadata.writeTo(buffer, 0);\n    value.writeTo(buffer, metadata.sizeInBytes());\n    return buffer;","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/parquet/src/main/java/org/apache/iceberg/parquet/ParquetVariantUtil.java#L93-L129","documentation":"ParquetVariantUtil.convert() maps a Parquet timestamp annotation to a variant PhysicalType, supporting MICROS (TIMESTAMPTZ/TIMESTAMPNTZ) and NANOS (TIMESTAMPTZ_NANOS/TIMESTAMPNTZ_NANOS). Any other unit hits the default branch and throws UnsupportedOperationException naming the unit.","triggerScenarios":"Converting a shredded variant timestamp whose TimestampLogicalTypeAnnotation unit is MILLIS (or any unit other than MICROS/NANOS) during variant shredding schema conversion.","commonSituations":"Files written with millis-precision timestamps shredded into variant columns; older writers emitting MILLIS units; schema defined before variant shredding spec restricted units to micros/nanos.","solutions":["Rewrite the column's logical type to MICROS or NANOS before shredding","Convert MILLIS values to MICROS in a preprocessing step and annotate accordingly","Upgrade Iceberg if support for the unit was added in a newer release"],"exampleFix":"// before: millis timestamp in shredded variant schema\nTypes.TimestampType ts = Types.TimestampType.withZone(); // written as MILLIS\n// after: normalize to micros\nTimestampLogicalTypeAnnotation.timestampType(true, TimeUnit.MICROS)","handlingStrategy":"validation","validationCode":"TimestampLogicalTypeAnnotation ts = (TimestampLogicalTypeAnnotation) annotation;\nPreconditions.checkArgument(\n    ts.getUnit() == TimeUnit.MICROS || ts.getUnit() == TimeUnit.NANOS,\n    \"Variant shredded timestamps must be MICROS or NANOS, got %s\", ts.getUnit());","typeGuard":"boolean isShreddableTimestampUnit(TimestampLogicalTypeAnnotation ts) {\n  return ts.getUnit() == TimeUnit.MICROS || ts.getUnit() == TimeUnit.NANOS;\n}","tryCatchPattern":"try {\n  physicalType = ParquetVariantUtil.convert(timestampAnnotation);\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage().startsWith(\"Invalid unit for shredded timestamp\")) {\n    // rewrite the column to micros, or keep the value unshredded\n  } else throw e;\n}","preventionTips":["Write shredded timestamp variants with micros or nanos only","Validate shredding schemas at file-writing time","Convert millis data upstream before shredding"],"tags":["variant","timestamp","shredding","unsupported-unit"],"backgroundTag":"unsupported-enum-value","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}