apache/seatunnel · error · java.lang.UnsupportedOperationException

Unsupported type %s for numeric minus.

Error message

Unsupported type %s for numeric minus.

What it means

ObjectUtils.minus() supports subtraction only for Integer, Short, Byte, Long, BigInteger, BigDecimal and (specially) String. For any other operand type it throws UnsupportedOperationException with the offending simple class name. String operands short-circuit to Long.MAX_VALUE, so only truly unsupported types reach this branch.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/utils/ObjectUtils.java:75

            return BigDecimal.valueOf((int) minuend).subtract(BigDecimal.valueOf((int) subtrahend));
        } else if (minuend instanceof Short) {
            return BigDecimal.valueOf((short) minuend)
                    .subtract(BigDecimal.valueOf((short) subtrahend));
        } else if (minuend instanceof Byte) {
            return BigDecimal.valueOf((byte) minuend)
                    .subtract(BigDecimal.valueOf((byte) subtrahend));
        } else if (minuend instanceof Long) {
            return BigDecimal.valueOf((long) minuend)
                    .subtract(BigDecimal.valueOf((long) subtrahend));
        } else if (minuend instanceof BigInteger) {
            return new BigDecimal(
                    ((BigInteger) minuend).subtract((BigInteger) subtrahend).toString());
        } else if (minuend instanceof BigDecimal) {
            return ((BigDecimal) minuend).subtract((BigDecimal) subtrahend);
        } else if (minuend instanceof String) {
            return BigDecimal.valueOf(Long.MAX_VALUE);
        } else {
            throw new UnsupportedOperationException(
                    String.format(
                            "Unsupported type %s for numeric minus.",
                            minuend.getClass().getSimpleName()));
        }
    }

    /**
     * Compares two comparable objects.
     *
     * @return The value {@code 0} if {@code num1} is equal to the {@code num2}; a value less than
     *     {@code 0} if the {@code num1} is numerically less than the {@code num2}; and a value
     *     greater than {@code 0} if the {@code num1} is numerically greater than the {@code num2}.
     * @throws ClassCastException if the compared objects are not instance of {@link Comparable} or
     *     not <i>mutually comparable</i> (for example, strings and integers).
     */
    @SuppressWarnings("unchecked")
    public static int compare(Object obj1, Object obj2) {
        Comparable<Object> c1 = (Comparable<Object>) obj1;

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Convert operands to BigDecimal before calling: ObjectUtils.minus(BigDecimal.valueOf(f1), BigDecimal.valueOf(f2)).
  2. Choose a supported numeric type as the split key (integer or decimal column) for incremental snapshot tables.
  3. If this arises inside SeaTunnel itself, upgrade or patch ObjectUtils to add the missing branch (e.g. Float/Double) since the plus() counterpart is similarly limited.

Example fix

// before
Object result = ObjectUtils.minus(floatVal1, floatVal2); // throws
// after
Object result = ObjectUtils.minus(
        BigDecimal.valueOf((Float) floatVal1), BigDecimal.valueOf((Float) floatVal2));
Defensive patterns

Strategy: validation

Validate before calling

static boolean isSupportedForMinus(Object o) {
    return o instanceof Integer || o instanceof Short || o instanceof Byte
        || o instanceof Long || o instanceof BigInteger || o instanceof BigDecimal
        || o instanceof String;
}

Type guard

if (!(o instanceof Number || o instanceof String)) {
    throw new IllegalArgumentException("minus supports Number/String only: " + o.getClass());
}

Try / catch

try {
    diff = ObjectUtils.minus(a, b);
} catch (UnsupportedOperationException e) {
    log.warn("falling back to BigDecimal subtraction", e);
    diff = BigDecimal.valueOf(((Number) a).doubleValue()).subtract(BigDecimal.valueOf(((Number) b).doubleValue()));
}

Prevention

When it happens

Trigger: Calling ObjectUtils.minus() with two same-class operands whose type is not one of the supported numeric types, e.g. Float, Double, java.util.Date, or a custom class.

Common situations: Incremental snapshot on a table with a FLOAT/DOUBLE split key, so chunk offsets are Float/Double values which minus() cannot handle.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/57b703ae6f287ee4. Report an issue: GitHub.