apache/flink · error · InvalidProgramException

The unary operation {} has no input.

Error message

The unary operation {} has no input.

What it means

Thrown by CollectionExecutor.executeUnaryOperator() when operator.getInput() returns null for a SingleInputOperator (e.g., MapOperator, FilterOperator, ReduceOperator). Every unary operator must have exactly one input; a null input means the operator was never connected to a preceding data source. This is an InvalidProgramException signaling a broken plan chain.

Source

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

        TaskInfo taskInfo = new TaskInfoImpl(typedSource.getName(), 1, 0, 1, 0);

        RuntimeUDFContext ctx;

        if (RichInputFormat.class.isAssignableFrom(
                typedSource.getUserCodeWrapper().getUserCodeClass())) {
            ctx = createContext(superStep, taskInfo, jobInfo);
        } else {
            ctx = null;
        }
        return typedSource.executeOnCollections(ctx, executionConfig);
    }

    private <IN, OUT> List<OUT> executeUnaryOperator(
            SingleInputOperator<?, ?, ?> operator, int superStep, JobInfo jobInfo)
            throws Exception {
        Operator<?> inputOp = operator.getInput();
        if (inputOp == null) {
            throw new InvalidProgramException(
                    "The unary operation " + operator.getName() + " has no input.");
        }

        @SuppressWarnings("unchecked")
        List<IN> inputData = (List<IN>) execute(inputOp, superStep, jobInfo);

        @SuppressWarnings("unchecked")
        SingleInputOperator<IN, OUT, ?> typedOp = (SingleInputOperator<IN, OUT, ?>) operator;

        // build the runtime context and compute broadcast variables, if necessary
        TaskInfo taskInfo = new TaskInfoImpl(typedOp.getName(), 1, 0, 1, 0);
        RuntimeUDFContext ctx;

        if (RichFunction.class.isAssignableFrom(typedOp.getUserCodeWrapper().getUserCodeClass())) {
            ctx = createContext(superStep, taskInfo, jobInfo);

            for (Map.Entry<String, Operator<?>> bcInputs :
                    operator.getBroadcastInputs().entrySet()) {

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Trace the input DataSet variable to find where it became null — check the transformation chain that should produce it.
  2. Use env.createPlanAsJSON() or print the execution plan to verify all operators have inputs.
  3. Ensure the source operator (env.fromElements, env.readTextFile, etc.) is non-null and properly chained to the unary operator.

Example fix

// before — input dataSet is null
DataSet<String> result = null;
result.map(x -> x.toUpperCase()).writeAsText(path);
// after
DataSet<String> source = env.fromElements("a", "b");
DataSet<String> result = source.map(x -> x.toUpperCase());
result.writeAsText(path);
Defensive patterns

Strategy: validation

Validate before calling

// Verify input DataSet is non-null before transformations
if (inputDataSet == null) {
    throw new IllegalStateException("Input DataSet for map/filter/reduce is null");
}
inputDataSet.map(fn);

Prevention

When it happens

Trigger: A SingleInputOperator (map, flatMap, filter, reduce, etc.) is created without an input. In the high-level API, this happens if the input DataSet passed to .map()/.filter() is null, or if the operator was constructed programmatically and setInput() was never called.

Common situations: A variable holding the input DataSet is null due to an earlier transformation error or a logic bug (e.g., assigning in an if-branch that was not taken). Also seen in unit tests that build operators manually without wiring inputs.

Related errors


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