apache/iceberg · error · IllegalArgumentException
Cannot convert to BigDecimal
Error message
Cannot convert to BigDecimal: ${value.getClass().getName()} What it means
convertDecimal converts values to Iceberg DecimalType: it accepts BigDecimal, Number (via BigDecimal.valueOf), and String (new BigDecimal(String)). Any other class throws IllegalArgumentException naming the class. The result is then rescaled to the column's fixed scale with HALF_UP rounding.
Solutions
- Emit numeric values (BigDecimal preferred to preserve precision) or decimal-parsable strings for decimal fields.
- Change the Iceberg column type if the data is genuinely a different type.
- Ensure the Connect converter/SMT doesn't wrap numbers in wrapper objects; unwrap before the sink.
- Catch IllegalArgumentException and route bad records to a DLQ.
Example fix
// before
record.set("price", true); // Boolean into DECIMAL(10,2)
// after
record.set("price", new BigDecimal("9.99")); Defensive patterns
Strategy: validation
Validate before calling
Object v = record.get("price");
if (!(v instanceof BigDecimal) && !(v instanceof Number) && !(v instanceof String)) {
throw new IllegalArgumentException("price must be decimal-compatible, got " + v.getClass().getSimpleName());
} Type guard
boolean isDecimalConvertible(Object v) {
return v instanceof BigDecimal || v instanceof Number || v instanceof String;
} Try / catch
try {
sink.write(record);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("Cannot convert to BigDecimal")) {
sendToDlq(record, e);
} else throw e;
} Prevention
- Prefer BigDecimal in producers for money fields to avoid precision loss from double conversion.
- Confirm the Connect decimal converter is enabled so decimal logical types arrive as BigDecimal.
- Check that string values parse as decimals before producing.
When it happens
Trigger: A field mapped to an Iceberg DecimalType column holding a Boolean, byte[], List, Map, or similar non-numeric non-string value.
Common situations: Decimal columns fed boolean or object JSON values; schemaless converters that wrap numbers in unexpected types; value objects from custom SMTs not unwrapped to numeric types.
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
- Cannot convert to boolean
- Cannot convert to double
- Cannot convert to float
- Cannot convert to int
- Cannot convert to long
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/77619d38bf38cd91.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java:474
throw new IllegalArgumentException("Cannot convert to double: " + value.getClass().getName());
}
protected BigDecimal convertDecimal(Object value, DecimalType type) {
BigDecimal bigDecimal;
if (value instanceof BigDecimal) {
bigDecimal = (BigDecimal) value;
} else if (value instanceof Number) {
Number num = (Number) value;
Double dbl = num.doubleValue();
if (dbl.equals(Math.floor(dbl))) {
bigDecimal = BigDecimal.valueOf(num.longValue());
} else {
bigDecimal = BigDecimal.valueOf(dbl);
}
} else if (value instanceof String) {
bigDecimal = new BigDecimal((String) value);
} else {
throw new IllegalArgumentException(
"Cannot convert to BigDecimal: " + value.getClass().getName());
}
return bigDecimal.setScale(type.scale(), RoundingMode.HALF_UP);
}
protected boolean convertBoolean(Object value) {
if (value instanceof Boolean) {
return (boolean) value;
} else if (value instanceof String) {
return Boolean.parseBoolean((String) value);
}
throw new IllegalArgumentException("Cannot convert to boolean: " + value.getClass().getName());
}
protected String convertString(Object value) {
try {
if (value instanceof String) {
return (String) value;View on GitHub (pinned to 86d9c8fc54)