apache/flink · error · IllegalArgumentException

Could not determine type information from inputs.

Error message

Could not determine type information from inputs.

What it means

Thrown by Operator.createUnionCascade when no output type can be determined from any input. The method tries input1 then input2[0] to infer the common type for the Union operators; if both are null (and input2 has length>0 but input2[0] is also null), type inference has nothing to work with. This indicates all provided operators are null in a context that expected at least one typed operator.

Source

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

     * @param input1 The first input operator.
     * @param input2 The other input operators.
     * @return The single operator or a cascade of unions of the operators.
     */
    public static <T> Operator<T> createUnionCascade(Operator<T> input1, Operator<T>... input2) {
        // return cases where we don't need a union
        if (input2 == null || input2.length == 0) {
            return input1;
        } else if (input2.length == 1 && input1 == null) {
            return input2[0];
        }

        TypeInformation<T> type = null;
        if (input1 != null) {
            type = input1.getOperatorInfo().getOutputType();
        } else if (input2.length > 0 && input2[0] != null) {
            type = input2[0].getOperatorInfo().getOutputType();
        } else {
            throw new IllegalArgumentException("Could not determine type information from inputs.");
        }

        // Otherwise construct union cascade
        Union<T> lastUnion =
                new Union<T>(new BinaryOperatorInformation<T, T, T>(type, type, type), "<unknown>");

        int i;
        if (input2[0] == null) {
            throw new IllegalArgumentException("The input may not contain null elements.");
        }
        lastUnion.setFirstInput(input2[0]);

        if (input1 != null) {
            lastUnion.setSecondInput(input1);
            i = 1;
        } else {
            if (input2[1] == null) {
                throw new IllegalArgumentException("The input may not contain null elements.");

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Ensure at least one non-null Operator with resolvable output type is passed.
  2. Filter nulls from the operators list before calling createUnionCascade.
  3. If input1 is legitimately null, guarantee input2[0] is non-null and typed.

Example fix

// before
Operator<T>[] ops = filterNulls(maybeWithNulls);
Operator.createUnionCascade(null, ops);  // ops[0] could be null

// after
Operator<T>[] ops = Arrays.stream(maybeWithNulls)
    .filter(Objects::nonNull)
    .toArray(Operator[]::new);
if (ops.length == 0) throw new IllegalStateException("no operators to union");
Operator.createUnionCascade(null, ops);
Defensive patterns

Strategy: validation

Validate before calling

if ((input1 == null)
        && (input2 == null || input2.length == 0 || input2[0] == null)) {
    throw new IllegalArgumentException(
        "At least one non-null typed operator is required.");
}

Prevention

When it happens

Trigger: Calling createUnionCascade(null, null, null) or createUnionCascade(nullOperator, nullOperator). Reaching the union-cascade logic with every source operator null.

Common situations: Building a union from a dynamically generated list that is all-null due to upstream failures. Legacy operator-graph construction code that passes null placeholders.

Related errors


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