{"record":{"id":"d7ffe832456c60a3","repo":"apache/beam","slug":"unsupported-timestamp-precision-precision","errorCode":null,"errorMessage":"Unsupported Timestamp precision: {precision}","messagePattern":"Unsupported Timestamp precision: (.+?)","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/IcebergUtils.java","lineNumber":232,"sourceCode":"      Schema.LogicalType<?, ?> logicalType = checkArgumentNotNull(beamType.getLogicalType());\n      if (logicalType instanceof FixedPrecisionNumeric) {\n        Row args = Preconditions.checkArgumentNotNull(logicalType.getArgument());\n        Integer precision = Preconditions.checkArgumentNotNull(args.getInt32(\"precision\"));\n        Integer scale = Preconditions.checkArgumentNotNull(args.getInt32(\"scale\"));\n        return new TypeAndMaxId(--nestedFieldId, Types.DecimalType.of(precision, scale));\n      }\n      if (logicalType instanceof PassThroughLogicalType) {\n        return beamFieldTypeToIcebergFieldType(logicalType.getBaseType(), nestedFieldId);\n      }\n      String logicalTypeIdentifier = logicalType.getIdentifier();\n      @Nullable Type type = BEAM_LOGICAL_TYPES_TO_ICEBERG_TYPES.get(logicalTypeIdentifier);\n      if (type == null) {\n        if (beamType.isLogicalType(Timestamp.IDENTIFIER)) {\n          int precision = checkStateNotNull(logicalType.getArgument());\n          if (precision == Timestamp.MICROS.getArgument()) {\n            type = Types.TimestampType.withZone();\n          } else {\n            throw new UnsupportedOperationException(\n                \"Unsupported Timestamp precision: \" + precision);\n          }\n        } else {\n          throw new RuntimeException(\"Unsupported Beam logical type \" + logicalTypeIdentifier);\n        }\n      }\n      return new TypeAndMaxId(--nestedFieldId, type);\n    } else if (beamType.getTypeName().isCollectionType()) { // ARRAY or ITERABLE\n      Schema.FieldType beamCollectionType =\n          Preconditions.checkArgumentNotNull(beamType.getCollectionElementType());\n\n      // nestedFieldId is reserved for the list's collection type.\n      // we increment here because further nested fields should use unique ID's\n      TypeAndMaxId listInfo =\n          beamFieldTypeToIcebergFieldType(beamCollectionType, nestedFieldId + 1);\n      Type icebergCollectionType = listInfo.type;\n\n      boolean elementTypeIsNullable =","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/IcebergUtils.java#L214-L250","documentation":"IcebergUtils.beamFieldTypeToIcebergFieldType maps a Beam Timestamp logical type to Iceberg's TimestampType.withZone() only when its precision argument equals Timestamp.MICROS. Any other precision (e.g. millis) is rejected with UnsupportedOperationException. Iceberg write conversion accepts only microsecond-precision timestamps with zone.","triggerScenarios":"Writing a Beam schema whose field is a Timestamp logical type with precision != Timestamp.MICROS.getArgument() (e.g. Timestamp.MILLIS) into an Iceberg table — thrown at IcebergUtils.java:232, including nested/list/map element types.","commonSituations":"PCollections built from sources emitting millisecond timestamps; custom logical types with non-micro precision; converting Avro/other millis-based schemas to Iceberg writes.","solutions":["Convert the field to microsecond precision (Timestamp.of(..., MICROS)) before writing.","Map the value to a supported type such as DateTime with micros precision in the Beam schema.","Preprocess the Row to convert timestamps to Instant/micros-backed fields.","If millisecond precision must be preserved, store the value as a LONG epoch field instead."],"exampleFix":"// before\nSchema.Field.of(\"ts\", Schema.FieldType.logicalType(Timestamp.of(Timestamp.MILLIS)));\n\n// after\nSchema.Field.of(\"ts\", Schema.FieldType.logicalType(Timestamp.of(Timestamp.MICROS)));","handlingStrategy":"validation","validationCode":"boolean ok = field.getType().isLogicalType(Timestamp.IDENTIFIER)\n    && Timestamp.MICROS.getArgument().equals(field.getType().getLogicalType().getArgument());","typeGuard":null,"tryCatchPattern":"try {\n  IcebergUtils.beamRowToIcebergRecord(schema, row);\n} catch (UnsupportedOperationException e) {\n  LOG.error(\"Timestamp precision not supported: {}\", e.getMessage());\n}","preventionTips":["Standardize on Timestamp.MICROS for all timestamp fields written to Iceberg.","Convert millis-based source timestamps to micros in a preprocessing map.","Document the precision requirement in pipeline schema definitions.","Assert field precision in unit tests for sink schemas."],"tags":["java","iceberg","timestamp","precision","type-conversion"],"backgroundTag":"unsupported-dtype","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}