apache/flink · error · InvalidProgramException
The binary operation {} has no first input.
Error message
The binary operation {} has no first input. What it means
Thrown by CollectionExecutor.executeBinaryOperator() when operator.getFirstInput() returns null for a DualInputOperator (e.g., JoinOperator, CoGroupOperator, CrossOperator). Binary operators require two inputs; if the first (left) input is null, the operator cannot execute. This is an InvalidProgramException indicating an incomplete join/cogroup/cross plan.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/common/operators/CollectionExecutor.java:283
operator.getBroadcastInputs().entrySet()) {
List<?> bcData = execute(bcInputs.getValue(), jobInfo);
ctx.setBroadcastVariable(bcInputs.getKey(), bcData);
}
} else {
ctx = null;
}
return typedOp.executeOnCollections(inputData, ctx, executionConfig);
}
private <IN1, IN2, OUT> List<OUT> executeBinaryOperator(
DualInputOperator<?, ?, ?, ?> operator, int superStep, JobInfo jobInfo)
throws Exception {
Operator<?> inputOp1 = operator.getFirstInput();
Operator<?> inputOp2 = operator.getSecondInput();
if (inputOp1 == null) {
throw new InvalidProgramException(
"The binary operation " + operator.getName() + " has no first input.");
}
if (inputOp2 == null) {
throw new InvalidProgramException(
"The binary operation " + operator.getName() + " has no second input.");
}
// compute inputs
@SuppressWarnings("unchecked")
List<IN1> inputData1 = (List<IN1>) execute(inputOp1, superStep, jobInfo);
@SuppressWarnings("unchecked")
List<IN2> inputData2 = (List<IN2>) execute(inputOp2, superStep, jobInfo);
@SuppressWarnings("unchecked")
DualInputOperator<IN1, IN2, OUT, ?> typedOp =
(DualInputOperator<IN1, IN2, OUT, ?>) operator;
// build the runtime context and compute broadcast variables, if necessaryView on GitHub (pinned to 2f3c205e92)
Solutions
- Verify the left input DataSet is non-null before calling .join()/.cogroup()/.cross().
- Inspect the execution plan (env.createPlanAsJSON()) to confirm the first input of each binary operator is wired.
- Trace the left input variable's assignment path for null-returning transformations or missed assignments.
Example fix
// before — leftInput is null DataSet<Tuple2> leftInput = null; leftInput.join(rightInput).where(0).equalTo(0); // after DataSet<Tuple2> leftInput = env.fromElements(Tuple2.of(1, "a")); leftInput.join(rightInput).where(0).equalTo(0);
Defensive patterns
Strategy: validation
Validate before calling
// Verify left input is non-null before join/cogroup/cross
if (leftInput == null) {
throw new IllegalStateException("Left input for join is null");
}
leftInput.join(rightInput).where(0).equalTo(0); Prevention
- Validate both join inputs are non-null before calling .join()/.cogroup()/.cross().
- Check the plan to confirm every DualInputOperator has both inputs wired.
- Trace left-input variable assignment paths for null-returning transformations.
When it happens
Trigger: A DualInputOperator (join, cogroup, cross, etc.) is created where the left input DataSet is null. In the high-level API this occurs when the first argument to .join()/.cogroup()/.crossWithHuge() is null or was never set.
Common situations: A left-input DataSet variable is null due to an upstream assignment bug, conditional logic that skipped the assignment, or a transformation that unexpectedly returned null. Common in complex pipelines where join inputs are computed conditionally.
Related errors
- The binary operation {} has no second input.
- The data sink {} has no input.
- The unary operation {} has no input.
- The iteration {} has no input (initial partial solution).
- The delta iteration {} has no initial solution set.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/7ace57a3c1e2ace2.
Report an issue: GitHub.