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

  1. Emit numeric values (BigDecimal preferred to preserve precision) or decimal-parsable strings for decimal fields.
  2. Change the Iceberg column type if the data is genuinely a different type.
  3. Ensure the Connect converter/SMT doesn't wrap numbers in wrapper objects; unwrap before the sink.
  4. 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

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


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)