{"record":{"id":"fa09ecf67f91ac21","repo":"apache/iceberg","slug":"unknown-logical-type-logicaltype","errorCode":null,"errorMessage":"Unknown logical type: ${logicalType}","messagePattern":"Unknown logical type: (.+?)","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/data/SparkPlannedAvroReader.java","lineNumber":156,"sourceCode":"          case \"timestamp-millis\":\n            // adjust to microseconds\n            ValueReader<Long> longs = ValueReaders.longs();\n            return (ValueReader<Long>) (decoder, ignored) -> longs.read(decoder, null) * 1000L;\n\n          case \"timestamp-micros\":\n            // Spark uses the same representation\n            return ValueReaders.longs();\n\n          case \"decimal\":\n            return SparkValueReaders.decimal(\n                ValueReaders.decimalBytesReader(primitive),\n                ((LogicalTypes.Decimal) logicalType).getScale());\n\n          case \"uuid\":\n            return SparkValueReaders.uuids();\n\n          default:\n            throw new IllegalArgumentException(\"Unknown logical type: \" + logicalType);\n        }\n      }\n\n      switch (primitive.getType()) {\n        case NULL:\n          return ValueReaders.nulls();\n        case BOOLEAN:\n          return ValueReaders.booleans();\n        case INT:\n          if (partner != null && partner.typeId() == Type.TypeID.LONG) {\n            return ValueReaders.intsAsLongs();\n          }\n          return ValueReaders.ints();\n        case LONG:\n          return ValueReaders.longs();\n        case FLOAT:\n          if (partner != null && partner.typeId() == Type.TypeID.DOUBLE) {\n            return ValueReaders.floatsAsDoubles();","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/data/SparkPlannedAvroReader.java#L138-L174","documentation":"The Iceberg Spark planned Avro reader throws IllegalArgumentException when an Avro schema field carries a logical type (e.g. decimal, uuid, date variants) that it does not recognize. The reader only maps the logical types in its switch (string, decimal, uuid, etc.); anything else is treated as an unsupported schema and fails fast instead of silently misreading data.","triggerScenarios":"Reading Avro data files (e.g. Avro-based manifest data or Avro table reads) where a field's Avro schema declares a logicalType not in the reader's supported set — for example custom/proprietary logical types, or Avro logical types added in newer Avro specs (duration, time-micros in some configurations).","commonSituations":"Data produced by writers using nonstandard Avro logical types; schema evolution introducing a new logical type while the Iceberg runtime is older; hand-authored Avro schemas in tests.","solutions":["Upgrade the Iceberg runtime to a version whose Avro reader supports the logical type in question","Rewrite/export the data with standard or no logical types (plain bytes/long/string)","Inspect the Avro schema of the failing field (avro-tools getschema) to identify the unsupported logicalType","Remove or convert the exotic logical type in the producing pipeline"],"exampleFix":"// before: producer writes fields with custom logicalType \"my-money\"\n// after: use a standard logical type or none\n{\"name\":\"amount\",\"type\":{\"type\":\"bytes\",\"logicalType\":\"decimal\",\"precision\":38,\"scale\":10}}","handlingStrategy":"validation","validationCode":"import org.apache.avro.Schema;\nboolean supported(Schema.Field f) {\n  Schema s = f.schema();\n  String lt = s.getLogicalType() != null ? s.getLogicalType().getName() : null;\n  return lt == null || lt.equals(\"decimal\") || lt.equals(\"uuid\") || lt.equals(\"string\")\n      || lt.equals(\"date\") || lt.equals(\"timestamp-millis\") || lt.equals(\"timestamp-micros\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  reader.read();\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().startsWith(\"Unknown logical type:\")) {\n    // re-export data with standard logical types or upgrade Iceberg\n  } else throw e;\n}","preventionTips":["Standardize producers on well-known Avro logical types","Diff file schemas with avro-tools getschema after schema evolution","Upgrade Iceberg before adopting newly specified Avro logical types"],"tags":["avro","spark","logical-type","reader"],"backgroundTag":"invalid-enum-value","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"}