apache/flink · error · VariantTypeException
Expecting a primitive variant but got %s
Error message
Expecting a primitive variant but got %s
What it means
BinaryVariant.get() switches on the variant's type tag and materializes the primitive value; the default branch throws VariantTypeException because the stored type is not one of the handled primitive kinds (it is likely an OBJECT or ARRAY, i.e. a compound value).
Source
Thrown at flink-core/src/main/java/org/apache/flink/types/variant/BinaryVariant.java:232
return getLong();
case FLOAT:
return getFloat();
case DOUBLE:
return getDouble();
case DECIMAL:
return getDecimal();
case STRING:
return getString();
case DATE:
return getDate();
case TIMESTAMP:
return getDateTime();
case TIMESTAMP_LTZ:
return getInstant();
case BYTES:
return getBytes();
default:
throw new VariantTypeException(
String.format("Expecting a primitive variant but got %s", getType()));
}
}
@Override
public <T> T getAs() throws VariantTypeException {
return (T) get();
}
@Override
public Variant getElement(int index) throws VariantTypeException {
return getElementAtIndex(index);
}
@Override
public int getArraySize() throws VariantTypeException {
return handleArray(value, pos, (size, offsetSize, offsetStart, dataStart) -> size);
}View on GitHub (pinned to 2f3c205e92)
Solutions
- Branch on getType() first: use getObject(...)/getArray(...) for OBJECT/ARRAY and get() for primitives
- If the value should be a scalar, fix the producer that wrote a nested object/array into this variant
- Use the typed accessors (getString, getLong, ...) which give clearer errors, after a type check
Example fix
// before
Object v = variant.get(); // throws if variant holds an object
// after
Object v;
switch (variant.getType()) {
case OBJECT: v = variant.getObject(); break;
case ARRAY: v = variant.getArray(); break;
default: v = variant.get(); break;
} Defensive patterns
Strategy: type-guard
Validate before calling
if (variant.getType() == VariantType.OBJECT || variant.getType() == VariantType.ARRAY) {
/* use getObject()/getArray() instead of get() */
} Type guard
static boolean isPrimitiveVariant(Variant v) {
VariantType t = v.getType();
return t != VariantType.OBJECT && t != VariantType.ARRAY;
} Try / catch
catch (VariantTypeException e) { /* fall back to per-type handling based on getType() */ } Prevention
- Always switch on getType() before accessing variant values
- Keep per-field variant types stable at the producer
- Add contract tests asserting scalar types for columns consumed via get()
When it happens
Trigger: Calling get()/getAs() on a Variant whose getType() is OBJECT or ARRAY (or an unknown future type tag). get() is intended for primitives only; getObject/getArray must be used for compound types.
Common situations: Schema-on-read pipelines where a column is Variant and some rows hold objects/arrays while code assumes scalars; upstream producer changed a field from a scalar to a nested object; generic code doing variant.getAs() without first checking type.
Related errors
- Configuration cannot evaluate value %s as a byte[] value
- Unrecognized type. This method is deprecated and might not w
- Could not stop with a savepoint job "{}".
- Could not stop with a detached savepoint job "{}".
- Failed to trigger a savepoint for the job {}.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/f70cc5b3b39169b2.
Report an issue: GitHub.