prestodb/presto · error · IllegalArgumentException
Unexpected type:
Error message
Unexpected type:
What it means
VariantUtil.getType decodes the Variant binary encoding: it reads the header byte at `position`, splits it into a basic type (low bits) and type-info (high bits), and maps the primitive type-info codes to a Type enum. This IllegalArgumentException is the MALFORMED_VARIANT guard thrown from the `default` branch when the type-info bits encode a value this library does not recognize — either the variant binary is corrupt/truncated or it was produced by a writer using a newer type code this reader does not know.
Source
Thrown at presto-parquet/src/main/java/com/facebook/presto/parquet/spark/VariantUtil.java:245
return Type.DOUBLE;
case DECIMAL4:
case DECIMAL8:
case DECIMAL16:
return Type.DECIMAL;
case DATE:
return Type.DATE;
case TIMESTAMP:
return Type.TIMESTAMP;
case TIMESTAMP_NTZ:
return Type.TIMESTAMP_NTZ;
case FLOAT:
return Type.FLOAT;
case BINARY:
return Type.BINARY;
case LONG_STR:
return Type.STRING;
default:
throw new IllegalArgumentException("Unexpected type: " + typeInfo);
}
}
}
private static IllegalStateException unexpectedType(Type type)
{
return new IllegalStateException("Expect type to be " + type);
}
// Get a boolean value from variant value `value[position...]`.
// Throw `MALFORMED_VARIANT` if the variant is malformed.
public static boolean getBoolean(byte[] value, int position)
{
checkIndex(position, value.length);
int basicType = value[position] & BASIC_TYPE_MASK;
int typeInfo = (value[position] >> BASIC_TYPE_BITS) & TYPE_INFO_MASK;
if (basicType != PRIMITIVE || (typeInfo != TRUE && typeInfo != FALSE)) {
throw unexpectedType(Type.BOOLEAN);View on GitHub (pinned to 55bb57d202)
Solutions
- Verify the producer and consumer use compatible Variant binary spec versions; upgrade the presto-parquet reader to match the writer
- Re-read the source Parquet file / regenerate the variant data to rule out corruption
- Validate the variant byte array (header byte, offsets, lengths) before calling getType
- Catch IllegalArgumentException from getType and treat the value as malformed rather than crashing the read
Example fix
// before
Type t = VariantUtil.getType(value, pos);
// after
Type t;
try {
t = VariantUtil.getType(value, pos);
} catch (IllegalArgumentException e) {
t = Type.NULL; // or surface a corrupt-row metric
} Defensive patterns
Strategy: try-catch
Validate before calling
// Java
static boolean looksLikeKnownVariantType(byte[] value, int position) {
if (position < 0 || position >= value.length) return false;
int basicType = value[position] & 0x3;
if (basicType == 0x1 || basicType == 0x2 || basicType == 0x3) return true; // SHORT_STR/OBJECT/ARRAY
int typeInfo = (value[position] >> 2) & 0x3f;
return typeInfo <= 15; // all known primitive type codes are contiguous low values
} Type guard
// Java
static boolean isReadableVariant(byte[] value, int position) {
try { VariantUtil.getType(value, position); return true; }
catch (RuntimeException e) { return false; }
} Try / catch
// Java
try {
Type t = VariantUtil.getType(value, pos);
// use t
} catch (IllegalArgumentException e) {
log.warn("Malformed variant type at pos " + pos, e);
// skip row / mark corrupt
} Prevention
- Keep the Parquet reader and the variant-producing engine on compatible versions
- Validate variant header bytes before interpreting values
- Treat IllegalArgumentException from VariantUtil as malformed-data, not a code bug
- Add metrics for malformed variant rows to detect producer regressions early
When it happens
Trigger: Calling VariantUtil.getType(byte[] value, int position) on a variant value whose header byte has basicType == PRIMITIVE but a typeInfo code not in the known set (NULL, TRUE/FALSE, INT1/2/4/8, DOUBLE, DECIMAL4/8/16, DATE, TIMESTAMP, TIMESTAMP_NTZ, FLOAT, BINARY, LONG_STR), typically because the bytes are corrupted or written by a newer Spark Variant spec.
Common situations: Reading Parquet files with variant columns written by a newer Spark/other-engine version that added type codes; corrupted or hand-crafted variant byte arrays; passing the wrong byte[] or a non-variant blob to getType.
Related errors
- Index out of bound: %s (size: %s)
- Invalid offset: %s > %s
- Decimal out of bound:
- Invalid day-time interval:
- Invalid year-month interval:
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/be714c1cfe25741e.
Report an issue: GitHub.