prestodb/presto · error · PrestoException

ICEBERG_INVALID_PARTITION_VALUE

ICEBERG_INVALID_PARTITION_VALUE

Error message

Invalid partition value '%s' for %s partition key: %s

What it means

IcebergUtil.deserializeIcebergValue parses the string-encoded partition value from Iceberg partition metadata into a Presto value of the column's type. When parsing fails (a thrown IllegalArgumentException from parseLong/parseFloat/parseDouble/Base64 decoding, BigDecimal construction, setScale with ROUND_UNNECESSARY, or a precision checkArgument), the code rethrows it as a PrestoException with code ICEBERG_INVALID_PARTITION_VALUE. This indicates the stored partition value string does not match the declared partition key type, i.e. table metadata is inconsistent or the value is out of the expected format/range.

Source

Thrown at presto-iceberg/src/main/java/com/facebook/presto/iceberg/IcebergUtil.java:954

                return parseLong(valueString);
            }
            if (type instanceof VarcharType) {
                return utf8Slice(valueString);
            }
            if (type.equals(VarbinaryType.VARBINARY)) {
                return wrappedBuffer(Base64.getDecoder().decode(valueString));
            }
            if (isShortDecimal(type) || isLongDecimal(type)) {
                DecimalType decimalType = (DecimalType) type;
                BigDecimal decimal = new BigDecimal(valueString);
                decimal = decimal.setScale(decimalType.getScale(), BigDecimal.ROUND_UNNECESSARY);
                checkArgument(decimal.precision() <= decimalType.getPrecision());
                BigInteger unscaledValue = decimal.unscaledValue();
                return isShortDecimal(type) ? unscaledValue.longValue() : Decimals.encodeUnscaledValue(unscaledValue);
            }
        }
        catch (IllegalArgumentException e) {
            throw new PrestoException(ICEBERG_INVALID_PARTITION_VALUE, format(
                    "Invalid partition value '%s' for %s partition key: %s",
                    valueString,
                    type.getDisplayName(),
                    name));
        }
        // Iceberg tables don't partition by non-primitive-type columns.
        throw new PrestoException(GENERIC_INTERNAL_ERROR, "Invalid partition type " + type.toString());
    }

    public static Domain createDomainFromIcebergPartitionValue(
            Object value,
            org.apache.iceberg.types.Type icebergType,
            Type prestoType)
    {
        if (value == null) {
            return onlyNull(prestoType);
        }

View on GitHub (pinned to 55bb57d202)

Solutions

  1. Inspect the table's partition metadata (e.g. via Iceberg metadata files or Spark) to find the offending partition key and value and verify it parses as the declared type
  2. Check whether the partition column type was evolved (ALTER) after data was written; rewrite/repair the affected partitions so values match the current schema
  3. Verify DECIMAL partition keys: values must have exactly the declared scale and not exceed the declared precision
  4. If the table was written by an incompatible engine version, rewrite the table metadata with a compatible writer (e.g. rewrite_data_files / migrate) or upgrade the connector
  5. File/inspect the table as an external table only after fixing metadata; as a workaround, exclude the corrupt partition from the query predicate

Example fix

// before: partition value string '3.14159' on DECIMAL(4,2) key
decimal = new BigDecimal("3.14159").setScale(2, ROUND_UNNECESSARY); // throws IllegalArgumentException -> ICEBERG_INVALID_PARTITION_VALUE
// after: repair the partition metadata so the stored value matches DECIMAL(4,2)
// e.g. rewrite the partition so the stored value is '3.14' (scale-2, precision <= 4)
Defensive patterns

Strategy: validation

Validate before calling

// Validate a partition value string before it reaches the connector
boolean isValidPartitionValue(String valueString, presto.spi.type.Type type) {
    if (valueString == null) return true;
    try {
        if (type.equals(BooleanType.BOOLEAN)) return valueString.equalsIgnoreCase("true") || valueString.equalsIgnoreCase("false");
        if (type.equals(BigintType.BIGINT) || type.equals(IntegerType.INTEGER) || type.equals(DateType.DATE)) Long.parseLong(valueString);
        else if (type.equals(RealType.REAL) || type.equals(DoubleType.DOUBLE)) Double.parseDouble(valueString);
        else if (type instanceof DecimalType) {
            DecimalType dt = (DecimalType) type;
            java.math.BigDecimal d = new java.math.BigDecimal(valueString).setScale(dt.getScale(), java.math.BigDecimal.ROUND_UNNECESSARY);
            if (d.precision() > dt.getPrecision()) return false;
        }
        else if (type.equals(VarbinaryType.VARBINARY)) java.util.Base64.getDecoder().decode(valueString);
        return true;
    } catch (RuntimeException e) { return false; }
}

Type guard

boolean isParsableAsLong(String s) {
    try { Long.parseLong(s); return true; } catch (NumberFormatException e) { return false; }
}

Try / catch

try {
    session.execute(query);
} catch (QueryFailedException e) {
    if (e.getErrorCode() == ICEBERG_INVALID_PARTITION_VALUE) {
        // skip/repair the offending partition; don't retry blindly
    } else throw e;
}

Prevention

When it happens

Trigger: Reading/deserializing Iceberg partition values during table scan when a partition value string cannot be converted: non-numeric text for an integer/bigint key, malformed boolean (not 'true'/'false'), non-Base64 binary, decimal string whose scale cannot be set without rounding, or a decimal whose precision exceeds the column's declared precision.

Common situations: Tables written by external engines (Spark/Flink) with differently formatted partition values; schema evolution that changed a partition column type after data was written; manually edited or corrupted metadata; DECIMAL partition columns where written values have more precision than declared; timestamp/time keys whose epoch value strings are corrupt.

Related errors


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