{"record":{"id":"5ec0c2a089cd0fca","repo":"apache/iceberg","slug":"unsupported-primitive-type-for-decimal-type","errorCode":null,"errorMessage":"Unsupported primitive type for decimal: <type>","messagePattern":"Unsupported primitive type for decimal: <type>","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"parquet/src/main/java/org/apache/iceberg/parquet/ParquetConversions.java","lineNumber":67,"sourceCode":"      case STRING:\n        return (T) ((Binary) value).toStringUsingUTF8();\n      case UUID:\n        return (T) UUIDUtil.convert(((Binary) value).toByteBuffer());\n      case FIXED:\n      case BINARY:\n        return (T) ((Binary) value).toByteBuffer();\n      case DECIMAL:\n        int scale =\n            ((DecimalLogicalTypeAnnotation) parquetType.getLogicalTypeAnnotation()).getScale();\n        switch (parquetType.getPrimitiveTypeName()) {\n          case INT32:\n          case INT64:\n            return (T) BigDecimal.valueOf(((Number) value).longValue(), scale);\n          case FIXED_LEN_BYTE_ARRAY:\n          case BINARY:\n            return (T) new BigDecimal(new BigInteger(((Binary) value).getBytes()), scale);\n          default:\n            throw new IllegalArgumentException(\n                \"Unsupported primitive type for decimal: \" + parquetType.getPrimitiveTypeName());\n        }\n      default:\n        throw new IllegalArgumentException(\"Unsupported primitive type: \" + type);\n    }\n  }\n\n  static Function<Object, Object> converterFromParquet(\n      PrimitiveType parquetType, Type icebergType) {\n    Function<Object, Object> fromParquet = converterFromParquet(parquetType);\n    if (icebergType != null) {\n      if (icebergType.typeId() == Type.TypeID.LONG\n          && parquetType.getPrimitiveTypeName() == PrimitiveType.PrimitiveTypeName.INT32) {\n        return value -> ((Integer) fromParquet.apply(value)).longValue();\n      } else if (icebergType.typeId() == Type.TypeID.DOUBLE\n          && parquetType.getPrimitiveTypeName() == PrimitiveType.PrimitiveTypeName.FLOAT) {\n        return value -> ((Float) fromParquet.apply(value)).doubleValue();\n      } else if (icebergType.typeId() == Type.TypeID.UUID) {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/parquet/src/main/java/org/apache/iceberg/parquet/ParquetConversions.java#L49-L85","documentation":"Thrown by ParquetConversions.convertValue when converting a Parquet value to an Iceberg DECIMAL value and the Parquet column's primitive type is neither INT32, INT64, FIXED_LEN_BYTE_ARRAY nor BINARY. Decimal values in Parquet must be stored in one of those physical types, so any other primitive reaching this converter is invalid.","triggerScenarios":"Reading data whose Parquet schema declares a decimal logical type on an unexpected physical primitive (e.g. a corrupted or handcrafted schema), calling convertValue directly with a mismatched parquetType.","commonSituations":"Hand-written or third-party Parquet files with nonstandard decimal encodings; schema mismatch between the writer and reader; buggy custom writer libraries.","solutions":["Rewrite/re-encode the Parquet file so the decimal column uses INT32/INT64/FIXED_LEN_BYTE_ARRAY/BINARY as appropriate for precision.","Fix the Parquet schema at write time to declare the correct physical type for the decimal logical type.","If you control the read path, use converterFromParquet only with compatible primitive types and guard the type beforehand."],"exampleFix":"// before\nTypes.DecimalType.of(38, 10) backed by a FLOAT Parquet column\n// after\ndeclare the column in Parquet as BINARY (DECIMAL logical type) or INT64 and re-encode the data","handlingStrategy":"validation","validationCode":"org.apache.parquet.schema.PrimitiveType pt = parquetType.asPrimitiveType();\nswitch (pt.getPrimitiveTypeName()) {\n  case INT32: case INT64: case FIXED_LEN_BYTE_ARRAY: case BINARY: break;\n  default: throw new IllegalStateException(\"Decimal column has invalid physical type: \" + pt.getPrimitiveTypeName());\n}","typeGuard":"boolean isDecimalSafe(PrimitiveType pt) {\n  return pt.getPrimitiveTypeName() == PrimitiveType.PrimitiveTypeName.INT32\n      || pt.getPrimitiveTypeName() == PrimitiveType.PrimitiveTypeName.INT64\n      || pt.getPrimitiveTypeName() == PrimitiveType.PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY\n      || pt.getPrimitiveTypeName() == PrimitiveType.PrimitiveTypeName.BINARY;\n}","tryCatchPattern":"try {\n  Object v = ParquetConversions.convertValue(parquetType, icebergType, ...);\n} catch (IllegalArgumentException e) {\n  throw new SchemaParseException(\"Parquet decimal column has incompatible physical type\", e);\n}","preventionTips":["Validate Parquet schemas at ingest time against the Iceberg schema before reading.","Standardize decimal physical types (INT32/INT64/FIXED_LEN_BYTE_ARRAY) in all writers.","Reject non-conforming files at scan planning rather than mid-read."],"tags":["parquet","decimal","type-mismatch","schema"],"backgroundTag":"type-mismatch","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"}