apache/flink · error · IllegalArgumentException

The grouping fields must not be empty.

Error message

The grouping fields must not be empty.

What it means

Thrown by ExpressionKeys(int[], TypeInformation, boolean) when keyPositions is null or empty and allowEmpty is false. Grouping/keying requires at least one field; an empty position array (without explicit allowance) means no key was supplied.

Solutions

  1. Ensure the positions array has at least one entry.
  2. If empty is genuinely valid in your flow, pass allowEmpty=true only when you handle the all-fields-selected semantics.
  3. Validate the array is non-empty before constructing ExpressionKeys.

Example fix

// before
int[] keys = fieldsFromConfig(); // possibly empty
ds.groupBy(keys);
// after
int[] keys = fieldsFromConfig();
if (keys.length == 0) throw new IllegalArgumentException("no key fields configured");
ds.groupBy(keys);
Defensive patterns

Strategy: validation

Validate before calling

if (keyPositions == null || keyPositions.length == 0) {
    throw new IllegalArgumentException("At least one grouping field is required");
}
new ExpressionKeys<>(keyPositions, type, false);

Prevention

When it happens

Trigger: Calling groupBy() with an empty int[] (e.g. groupBy(new int[0])); passing a null positions array; building positions from a list that turned out empty.

Common situations: Programmatic key construction where the field list is conditionally empty; passing a config-driven field array that resolved to zero entries; refactors that strip all fields but leave the call.

Related errors


AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14). Data as JSON: /api/errors/50f63781dacdf67e. Report an issue: GitHub.

Appendix: source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/operators/Keys.java:250

        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");

            // extract key field types
            CompositeType<T> cType = (CompositeType<T>) type;
            this.keyFields = new ArrayList<>(type.getTotalFields());

View on GitHub (pinned to 2f3c205e92)