apache/iceberg · error · IllegalArgumentException
Invalid primitive type for decimal:
Error message
Invalid primitive type for decimal:
What it means
ValueReaders.decimalBytesReader supports decimals stored as Avro FIXED or BYTES; any other Avro primitive type cannot carry decimal bytes and triggers this IllegalArgumentException. It guards the schema used for the logical decimal type.
Source
Thrown at core/src/main/java/org/apache/iceberg/avro/ValueReaders.java:142
return BytesReader.INSTANCE;
}
public static ValueReader<ByteBuffer> byteBuffers() {
return ByteBufferReader.INSTANCE;
}
public static ValueReader<BigDecimal> decimal(ValueReader<byte[]> unscaledReader, int scale) {
return new DecimalReader(unscaledReader, scale);
}
public static ValueReader<byte[]> decimalBytesReader(Schema schema) {
switch (schema.getType()) {
case FIXED:
return ValueReaders.fixed(schema.getFixedSize());
case BYTES:
return ValueReaders.bytes();
default:
throw new IllegalArgumentException(
"Invalid primitive type for decimal: " + schema.getType());
}
}
public static ValueReader<Variant> variants() {
return VariantReader.INSTANCE;
}
public static ValueReader<Object> union(List<ValueReader<?>> readers) {
return new UnionReader(readers);
}
public static ValueReader<Long> positions() {
return new PositionReader();
}
public static <T> ValueReader<Collection<T>> array(ValueReader<T> elementReader) {
return new ArrayReader<>(elementReader);View on GitHub (pinned to 86d9c8fc54)
Solutions
- Fix the Avro schema so the decimal field's type is bytes with logicalType 'decimal' or fixed with the required byte size
- Compute the required bytes with TypeUtil.decimalRequiredBytes(precision) when using fixed
- Rewrite the file with a writer that follows the Iceberg Avro encoding for decimals
Example fix
// before
{"type": "string", "logicalType": "decimal", "precision": 10, "scale": 2}
// after
{"type": "bytes", "logicalType": "decimal", "precision": 10, "scale": 2} Defensive patterns
Strategy: validation
Validate before calling
Schema.Field f = schema.getField("amount");
Schema type = f.schema().getTypes().size() > 1 ? f.schema().getTypes().get(1) : f.schema();
boolean ok = type.getType() == Schema.Type.BYTES || type.getType() == Schema.Type.FIXED; Type guard
boolean decimalSchemaOk(Schema s) { return s.getLogicalType() instanceof LogicalTypes.Decimal && (s.getType() == Schema.Type.BYTES || s.getType() == Schema.Type.FIXED); } Try / catch
try { ValueReader<BigDecimal> r = ValueReaders.decimals(schema); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Invalid primitive type for decimal")) { /* fix schema */ } else throw e; } Prevention
- Verify decimal fields are bytes/fixed after any schema round-trip through external tools
- Match fixed size to TypeUtil.decimalRequiredBytes(precision)
- Regenerate schemas from the Iceberg schema rather than editing JSON by hand
When it happens
Trigger: Reading an Avro schema where a decimal logical type is attached to an unexpected primitive (e.g. STRING or INT) instead of FIXED (with fixed-size) or BYTES.
Common situations: Hand-written or tool-rewritten Avro schemas losing the underlying primitive type; foreign writers serializing decimals incorrectly; schema translation bugs.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unsupported base type for decimal: " + primitive.getPrimitiv
- Cannot parse default as a %s value: %s
- Unsupported type: variant
- Cannot coerce value to int:
- Unsupported type: variant
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/023c23b737b3c3f6.
Report an issue: GitHub.