{"record":{"id":"e82c7cf509660121","repo":"apache/beam","slug":"unsupported-beam-logical-type-logicaltypeidentifier","errorCode":null,"errorMessage":"Unsupported Beam logical type {logicalTypeIdentifier}","messagePattern":"Unsupported Beam logical type (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/IcebergUtils.java","lineNumber":236,"sourceCode":"        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 =\n          Preconditions.checkArgumentNotNull(beamType.getCollectionElementType()).getNullable();\n\n      Type listType =\n          elementTypeIsNullable","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/IcebergUtils.java#L218-L254","documentation":"When converting a Beam field type to Iceberg, if the type is a logical type that is not a recognized Timestamp and no direct Iceberg mapping was found, beamFieldTypeToIcebergFieldType throws RuntimeException naming the logical type identifier. It marks Beam logical types the Iceberg writer cannot express.","triggerScenarios":"Writing a Beam schema containing a custom or unsupported logical type (neither a primitive with a direct mapping nor Timestamp.MICROS) at IcebergUtils.java:236; also reached recursively via list/key/value element types.","commonSituations":"Custom LogicalType implementations in user pipelines; exotic logical types from third-party Beam IOs feeding an Iceberg sink; schema fields like enums or custom money/duration logical types.","solutions":["Convert the field to a base Beam type (string, long, double, bytes) before writing to Iceberg.","Implement/serialize the logical type to a primitive representation in a preprocessing step.","Remove or replace the custom logical type field in the schema handed to the Iceberg sink.","If the type should be supported, upgrade Beam or file/patch IcebergUtils to add a mapping."],"exampleFix":"// before\nSchema.Field.of(\"amount\", Schema.FieldType.logicalType(new MoneyLogicalType()));\n\n// after\nSchema.Field.of(\"amount\", Schema.FieldType.DECIMAL);","handlingStrategy":"validation","validationCode":"for (Schema.Field f : beamSchema.getFields()) {\n  if (f.getType().getTypeName().isLogicalType()\n      && !f.getType().isLogicalType(Timestamp.IDENTIFIER)) {\n    throw new IllegalStateException(\"Unsupported logical type on field: \" + f.getName());\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  IcebergUtils.beamRowToIcebergRecord(schema, row);\n} catch (RuntimeException e) {\n  LOG.error(\"Unsupported Beam logical type: {}\", e.getMessage());\n}","preventionTips":["Avoid custom logical types in schemas destined for Iceberg sinks.","Serialize complex domain types to primitives upstream.","Restrict sink schemas to primitive + micros Timestamp fields.","Test schema-to-Iceberg conversion in CI."],"tags":["java","iceberg","logical-type","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"}