prestodb/presto · error · IllegalArgumentException

Unexpected decimal type:

Error message

Unexpected decimal type: 

What it means

TpcdsTableStatisticsFactory.toDouble converts a decoded statistics value to double; for decimal values it only handles short (64-bit) and long (128-bit) decimals via isShortDecimal/isLongDecimal. A decimal value that is neither, or a DecimalType variant it does not recognize, triggers 'Unexpected decimal type'. It is an internal invariant violation in statistics conversion.

Source

Thrown at presto-tpcds/src/main/java/com/facebook/presto/tpcds/statistics/TpcdsTableStatisticsFactory.java:112

    }

    private static double toDouble(Object value, Type type)
    {
        if (value instanceof String && type.equals(DATE)) {
            return LocalDate.parse((CharSequence) value).toEpochDay();
        }
        if (type.equals(BIGINT) || type.equals(INTEGER) || type.equals(DATE)) {
            return ((Number) value).doubleValue();
        }
        if (type instanceof DecimalType) {
            DecimalType decimalType = (DecimalType) type;
            if (isShortDecimal(decimalType)) {
                return parseDouble(Decimals.toString(((Number) value).longValue(), decimalType.getScale()));
            }
            if (isLongDecimal(decimalType)) {
                return parseDouble(Decimals.toString((Slice) value, decimalType.getScale()));
            }
            throw new IllegalArgumentException("Unexpected decimal type: " + decimalType);
        }
        if (type.equals(DOUBLE)) {
            return ((Number) value).doubleValue();
        }
        throw new IllegalArgumentException("unsupported column type " + type);
    }
}

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Ensure statistics blocks use standard Presto DecimalType instances (createDecimalType)
  2. Check the decimalType precision is within 1..38 so short/long classification works
  3. Upgrade Presto if a type-system change broke isShortDecimal/isLongDecimal classification
  4. Report/investigate which plugin supplied the non-standard decimal type

Example fix

// before
Type t = new MyCustomDecimalType(p, s);
// after
Type t = DecimalType.createDecimalType(p, s);
Defensive patterns

Strategy: type-guard

Validate before calling

if (type instanceof DecimalType) {
    DecimalType d = (DecimalType) type;
    if (d.getPrecision() < 1 || d.getPrecision() > 38) {
        throw new IllegalArgumentException("Decimal precision out of range: " + d);
    }
} else if (!type.equals(DOUBLE)) {
    throw new IllegalArgumentException("Stats conversion requires decimal or double, got " + type);
}

Type guard

boolean isSupportedNumeric(Type t) {
    return t.equals(DOUBLE) || (t instanceof DecimalType && ((DecimalType) t).getPrecision() <= 38);
}

Try / catch

try {
    double d = toDouble(type, value);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Unexpected decimal type")) {
        throw new IllegalStateException("Non-standard decimal type in stats block: " + e.getMessage(), e);
    }
    throw e;
}

Prevention

When it happens

Trigger: toRange building a stats range from a column block value typed as decimal but whose Type instance is not classified as short or long decimal (e.g. an unexpected DecimalType implementation or precision outside 1-38).

Common situations: Custom or third-party Type implementations for decimals feeding statistics conversion; internal Presto type-system changes; statistics blocks built with mismatched type metadata.

Related errors


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/47a13e712064e66a. Report an issue: GitHub.