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
- Only pass STRING, UUID, or binary-backed primitives to convertValue; handle numeric/date primitives with dedicated branches
- Add a conversion branch for the offending PhysicalType if it should be supported
- 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
- Match literal conversion branches to all PhysicalType values you can encounter
- Only use convertValue on string/uuid/binary bounds
- Add exhaustive switch tests for PhysicalType conversions
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
- Invalid bit width for int
- Invalid bit width for int
- Invalid primitive type for decimal
- Invalid primitive type for decimal
- Invalid unit for shredded timestamp
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)