apache/iceberg · error · java.lang.UnsupportedOperationException
Unsupported base type for decimal
Error message
Unsupported base type for decimal: ${desc.getPrimitiveType().getPrimitiveTypeName()} What it means
Iceberg's Flink Parquet writer visits a Parquet column of logical decimal type and chooses a writer based on the underlying physical Parquet type (INT32, INT64, BINARY, FIXED_LEN_BYTE_ARRAY). If the physical type is none of those, no decimal writer exists and the library throws this UnsupportedOperationException. This indicates malformed or unsupported Parquet schema rather than bad user data.
Solutions
- Check the Parquet file's schema with parquet-tools and fix the physical type to INT32, INT64, BINARY, or FIXED_LEN_BYTE_ARRAY for the decimal column
- Regenerate the file with a standards-compliant writer (Spark/Iceberg)
- If this is a legitimately new physical encoding, extend FlinkParquetWriters.decimal switch to support it and file an upstream issue
Example fix
// before: file written with nonstandard physical type FLOAT + decimal annotation
// after: rewrite the table so decimals use a valid physical type
spark.sql("CREATE TABLE fixed STORED BY iceberg AS SELECT CAST(dec_col AS DECIMAL(20,6)) FROM bad") Defensive patterns
Strategy: validation
Validate before calling
org.apache.parquet.schema.PrimitiveType pt = desc.getPrimitiveType();
if (!(pt.getPrimitiveTypeName() == PrimitiveTypeName.INT32 || pt.getPrimitiveTypeName() == PrimitiveTypeName.INT64 || pt.getPrimitiveTypeName() == PrimitiveTypeName.BINARY || pt.getPrimitiveTypeName() == PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY)) {
throw new IllegalArgumentException("Column " + desc + " has invalid physical type for decimal: " + pt.getPrimitiveTypeName());
} Try / catch
try { writer = FlinkParquetWriters.buildWriter(...); } catch (UnsupportedOperationException e) { if (e.getMessage().startsWith("Unsupported base type for decimal")) { /* repair schema or reroute */ } else throw e; } Prevention
- Inspect Parquet schema with parquet-tools before ingesting third-party files
- Only write decimals with Spark/Iceberg-compliant writers
- Validate physical/logical type pairs in a schema check step
When it happens
Trigger: Writing decimal data through FlinkParquetWriters when the Parquet ColumnDescriptor's physical primitive type is not INT32/INT64/BINARY/FIXED_LEN_BYTE_ARRAY (e.g. FLOAT/DOUBLE or BOOLEAN physical type carrying a decimal logical annotation), typically from corrupt or non-standard Parquet files.
Common situations: Reading/writing Parquet files produced by third-party tools that attach a decimal logical type to an unexpected physical type; corrupted schema metadata; manually crafted Parquet schemas.
Related errors
- Unsupported base type for decimal
- Unsupported base type for decimal:
- Unsupported base type for decimal:
- Unsupported base type for decimal:
- Unsupported base type for decimal
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/5924bc3e0602132d.
Report an issue: GitHub.
Appendix: source
Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/data/FlinkParquetWriters.java:253
return Optional.of(strings(desc));
}
@Override
public Optional<ParquetValueWriter<?>> visit(DecimalLogicalTypeAnnotation decimal) {
ParquetValueWriter<DecimalData> writer;
switch (desc.getPrimitiveType().getPrimitiveTypeName()) {
case INT32:
writer = decimalAsInteger(desc, decimal.getPrecision(), decimal.getScale());
break;
case INT64:
writer = decimalAsLong(desc, decimal.getPrecision(), decimal.getScale());
break;
case BINARY:
case FIXED_LEN_BYTE_ARRAY:
writer = decimalAsFixed(desc, decimal.getPrecision(), decimal.getScale());
break;
default:
throw new UnsupportedOperationException(
"Unsupported base type for decimal: "
+ desc.getPrimitiveType().getPrimitiveTypeName());
}
return Optional.of(writer);
}
@Override
public Optional<ParquetValueWriter<?>> visit(DateLogicalTypeAnnotation dates) {
return Optional.of(ints(flinkType, desc));
}
@Override
public Optional<ParquetValueWriter<?>> visit(TimeLogicalTypeAnnotation times) {
Preconditions.checkArgument(
LogicalTypeAnnotation.TimeUnit.MICROS.equals(times.getUnit()),
"Cannot write time in %s, only MICROS is supported",
times.getUnit());
return Optional.of(timeMicros(desc));View on GitHub (pinned to 86d9c8fc54)