apache/flink · error · InvalidProgramException
Tuple size must be greater than 0. Size: {type.getArity()}
Error message
Tuple size must be greater than 0. Size: {type.getArity()} What it means
Thrown by ExpressionKeys(int[], TypeInformation, boolean) when the tuple type reports arity 0. A tuple with zero fields cannot provide any key position; the constructor rejects it because there is nothing to key on.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java:246
this(new int[] {keyPosition}, type, false);
}
/** Create int-based (non-nested) field position keys on a tuple type. */
public ExpressionKeys(int[] keyPositions, TypeInformation<T> type) {
this(keyPositions, type, false);
}
/** Create int-based (non-nested) field position keys on a tuple type. */
public ExpressionKeys(int[] keyPositions, TypeInformation<T> type, boolean allowEmpty) {
if (!type.isTupleType() || !(type instanceof CompositeType)) {
throw new InvalidProgramException(
"Specifying keys via field positions is only valid "
+ "for tuple data types. Type: "
+ type);
}
if (type.getArity() == 0) {
throw new InvalidProgramException(
"Tuple size must be greater than 0. Size: " + type.getArity());
}
if (!allowEmpty && (keyPositions == null || keyPositions.length == 0)) {
throw new IllegalArgumentException("The grouping fields must not be empty.");
}
this.keyFields = new ArrayList<>();
if (keyPositions == null || keyPositions.length == 0) {
// use all tuple fields as key fields
keyPositions = createIncrIntArray(type.getArity());
} else {
rangeCheckFields(keyPositions, type.getArity() - 1);
}
checkArgument(
keyPositions.length > 0, "Grouping fields can not be empty at this point");
View on GitHub (pinned to 2f3c205e92)
Solutions
- Avoid keying on a zero-arity tuple; restructure the upstream to emit a real key field.
- If the type is a placeholder, replace it with a tuple that has at least one field.
- Validate type.getArity() > 0 before building position-based keys.
Example fix
// before DataSet<Tuple0> ds = ...; ds.groupBy(0); // after DataSet<Tuple1<String>> ds = upstream.map(x -> Tuple1.of(x.id)); ds.groupBy(0);
Defensive patterns
Strategy: validation
Validate before calling
if (type.getArity() == 0) {
throw new IllegalArgumentException("Tuple type has arity 0; cannot build position keys: " + type);
} Type guard
static <T> boolean hasFields(TypeInformation<T> t) { return t.getArity() > 0; } Prevention
- Do not key on zero-arity tuples (Tuple0/Unit); emit a real key field upstream.
- Validate arity > 0 before constructing position-based ExpressionKeys.
- Avoid placeholder TypeInformation in tests that reports zero fields.
When it happens
Trigger: Constructing ExpressionKeys against a Tuple0 type (e.g. Tuple0/Unit from Scala interop, or a degenerate case TypeInfo reporting arity 0); passing a custom CompositeType whose getArity() returns 0.
Common situations: Scala/Java interop producing a Unit/Tuple0 stream then trying to key it; programmatically-built TypeInformation that erroneously reports zero arity; tests with placeholder tuple types.
Related errors
- Specifying keys via field positions is only valid for tuple
- The grouping fields must not be empty.
- This type ({ffd.getType()}) cannot be used as key.
- Expression key may not be null.
- Unable to extract key from expression '{keyExpr}' on key {cT
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/85b7a09f34397cc6.
Report an issue: GitHub.