apache/iceberg · error · IllegalArgumentException

Invalid primitive type for decimal

Error message

Invalid primitive type for decimal: ${primitive}

What it means

Thrown by VariantReaderBuilder.variantDecimalType() when a shredded decimal typed_value column's physical type is neither INT32 nor INT64 (DECIMAL4/DECIMAL8). Variant decimal shredding only supports INT32- and INT64-backed decimals; FLBA/BINARY-backed wide decimals are rejected.

Solutions

  1. Rewrite the shredded decimal so it is backed by INT32 (precision <= 9) or INT64 (precision <= 18).
  2. Keep high-precision values unshredded inside the Variant binary instead of a typed decimal column.
  3. Change the producing writer to select an INT32/INT64-backed decimal when shredding.

Example fix

// before
Types.required(PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY).length(16).as(DecimalLogicalType.decimalType(38, 10)).named("typed_value")

// after (precision within 18)
Types.required(PrimitiveTypeName.INT64).as(DecimalLogicalType.decimalType(18, 10)).named("typed_value")
Defensive patterns

Strategy: validation

Validate before calling

PrimitiveTypeName p = typedValue.getType().asPrimitiveType().getPrimitiveTypeName();
Preconditions.checkArgument(p == INT32 || p == INT64,
    "Shredded decimals must be INT32/INT64-backed, got %s", p);

Type guard

boolean isShreddableDecimal(Type t) {
  if (!t.isPrimitive()) return false;
  PrimitiveTypeName p = t.asPrimitiveType().getPrimitiveTypeName();
  return p == PrimitiveTypeName.INT32 || p == PrimitiveTypeName.INT64;
}

Try / catch

try {
  openVariantReader(schema);
} catch (IllegalArgumentException e) {
  if (e.getMessage().startsWith("Invalid primitive type for decimal")) {
    readUnshreddedVariant(column); // wide decimals stay in variant binary
  } else throw e;
}

Prevention

When it happens

Trigger: Reading a shredded Variant decimal whose typed_value physical primitive is not INT32/INT64 (e.g. FIXED_LEN_BYTE_ARRAY or BINARY decimal) via primitive() -> variantDecimalType.

Common situations: Writers shredding high-precision decimals (precision > 18) which require FLBA/BINARY backing; tooling defaulting decimals to fixed-length byte arrays; cross-system schemas where decimal backing differs.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/685672924beb862d. Report an issue: GitHub.

Appendix: source

Thrown at parquet/src/main/java/org/apache/iceberg/parquet/VariantReaderBuilder.java:285

    @Override
    public Optional<VariantValueReader> visit(UUIDLogicalTypeAnnotation logical) {
      VariantValueReader reader =
          ParquetVariantReaders.asVariant(PhysicalType.UUID, ParquetValueReaders.uuids(desc));
      return Optional.of(reader);
    }

    private static PhysicalType variantDecimalType(PrimitiveType primitive) {
      switch (primitive.getPrimitiveTypeName()) {
        case FIXED_LEN_BYTE_ARRAY:
        case BINARY:
          return PhysicalType.DECIMAL16;
        case INT64:
          return PhysicalType.DECIMAL8;
        case INT32:
          return PhysicalType.DECIMAL4;
      }

      throw new IllegalArgumentException("Invalid primitive type for decimal: " + primitive);
    }
  }
}

View on GitHub (pinned to 86d9c8fc54)