apache/iceberg · error · IllegalStateException

Invalid bound type

Error message

Invalid bound type: <primitive>

What it means

ParquetVariantUtil.convertValue() converts a Parquet Binary-backed primitive bound value into the target type for STRING, UUID and Binary->ByteBuffer cases. For any other primitive physical type it throws IllegalStateException, because the bound value's type cannot be converted.

Solutions

  1. Only pass STRING, UUID, or binary-backed primitives to convertValue; handle numeric/date primitives with dedicated branches
  2. Add a conversion branch for the offending PhysicalType if it should be supported
  3. Validate the variant metadata's primitive type before calling convertValue

Example fix

// before: passing an INT32 bound value into convertValue
Object v = ParquetVariantUtil.convertValue(PhysicalType.INT32, binary);
// after: branch on type first
switch (type) { case INT32: return binary.getInteger(); case STRING: ... }
Defensive patterns

Strategy: type-guard

Validate before calling

Preconditions.checkArgument(
    primitive == PhysicalType.STRING || primitive == PhysicalType.UUID,
    "convertValue only supports binary-backed primitives, got %s", primitive);

Type guard

boolean isBinaryBackedPrimitive(PhysicalType p) {
  return p == PhysicalType.STRING || p == PhysicalType.UUID;
}

Try / catch

try {
  value = ParquetVariantUtil.convertValue(primitive, binary);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Invalid bound type")) {
    // handle numeric/date primitives on a dedicated path
  } else throw e;
}

Prevention

When it happens

Trigger: Calling convertValue on a variant bound/primitive value whose PhysicalType is not STRING, UUID or a Binary-backed type — e.g. INT32/INT64/FLOAT/DOUBLE or DATE/TIME types reaching the Binary conversion branch.

Common situations: Shredding schemas that bind literal values of numeric primitives; bugs in variant predicate/literal conversion paths; version drift between the shredding spec support and this converter.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at parquet/src/main/java/org/apache/iceberg/parquet/ParquetVariantUtil.java:174

      case DOUBLE:
        return (T) value;
      case INT8:
        return (T) (Byte) ((Number) value).byteValue();
      case INT16:
        return (T) (Short) ((Number) value).shortValue();
      case DECIMAL4:
      case DECIMAL8:
        return (T) BigDecimal.valueOf(((Number) value).longValue(), scale);
      case DECIMAL16:
        return (T) new BigDecimal(new BigInteger(((Binary) value).getBytes()), scale);
      case BINARY:
        return (T) ((Binary) value).toByteBuffer();
      case STRING:
        return (T) ((Binary) value).toStringUsingUTF8();
      case UUID:
        return (T) UUIDUtil.convert(((Binary) value).getBytes());
      default:
        throw new IllegalStateException("Invalid bound type: " + primitive);
    }
  }

  /**
   * Returns a comparator for values of the given primitive {@link PhysicalType type}.
   *
   * @param primitive a primitive variant {@link PhysicalType}
   * @param <T> Java type used for values of the given Variant physical type
   * @return a comparator for in-memory values of the given type
   */
  @SuppressWarnings("unchecked")
  static <T> Comparator<T> comparator(PhysicalType primitive) {
    switch (primitive) {
      case BINARY:
        return (Comparator<T>) Comparators.unsignedBytes();
      case STRING:
        return (Comparator<T>) Comparators.charSequences();
      default:

View on GitHub (pinned to 86d9c8fc54)