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
- 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
- Check whether the partition column type was evolved (ALTER) after data was written; rewrite/repair the affected partitions so values match the current schema
- Verify DECIMAL partition keys: values must have exactly the declared scale and not exceed the declared precision
- 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
- 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
- Keep partition column types primitive and stable; avoid evolving partition column types after writes
- Validate DECIMAL partition keys: written values must match declared scale and precision exactly
- Write Iceberg tables only with engines whose writer versions format partition values compatibly
- Audit partition metadata after external writes or manual metadata edits
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
- HIVE_INVALID_METADATA
- HIVE_INVALID_PARTITION_VALUE
- HUDI_INVALID_PARTITION_VALUE
- ICEBERG_INVALID_METADATA
- Table metadata is missing
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/a55c4e80e6d3494e.
Report an issue: GitHub.