apache/flink · error · InvalidProgramException

No termination condition is set (neither fix number of itera

Error message

No termination condition is set (neither fix number of iteration nor termination criterion).

What it means

Thrown by BulkIterationBase.validate() as an InvalidProgramException when the iteration has neither a termination criterion (setTerminationCriterion was never called) nor a valid positive iteration count (numberOfIterations <= 0). Without either, the iteration would run indefinitely. The default numberOfIterations is -1, so this triggers if setMaximumNumberOfIterations was never called and no termination criterion was set.

Source

Thrown at flink-core/src/main/java/org/apache/flink/api/common/operators/base/BulkIterationBase.java:176

    @Override
    public AggregatorRegistry getAggregators() {
        return this.aggregators;
    }

    /**
     * @throws InvalidProgramException
     */
    public void validate() throws InvalidProgramException {
        if (this.input == null) {
            throw new RuntimeException("Operator for initial partial solution is not set.");
        }
        if (this.iterationResult == null) {
            throw new InvalidProgramException(
                    "Operator producing the next version of the partial "
                            + "solution (iteration result) is not set.");
        }
        if (this.terminationCriterion == null && this.numberOfIterations <= 0) {
            throw new InvalidProgramException(
                    "No termination condition is set "
                            + "(neither fix number of iteration nor termination criterion).");
        }
    }

    /**
     * The BulkIteration meta operator cannot have broadcast inputs.
     *
     * @return An empty map.
     */
    public Map<String, Operator<?>> getBroadcastInputs() {
        return Collections.emptyMap();
    }

    /**
     * The BulkIteration meta operator cannot have broadcast inputs. This method always throws an
     * exception.
     *

View on GitHub (pinned to 2f3c205e92)

Solutions

  1. Always call iteration.setMaximumNumberOfIterations(n) with n >= 1, or set a termination criterion via iteration.setTerminationCriterion(criterionOperator).
  2. If using data-driven termination, call setTerminationCriterion with an operator that produces an empty dataset when converged.
  3. Call validate() early in development to catch missing termination configuration before job submission.

Example fix

// before
BulkIterationBase<MyType> iteration = new BulkIterationBase<>(operatorInfo, "my-iter");
iteration.setInput(dataSource);
iteration.setNextPartialSolution(stepFunction);
// no termination set
iteration.validate(); // throws

// after
BulkIterationBase<MyType> iteration = new BulkIterationBase<>(operatorInfo, "my-iter");
iteration.setInput(dataSource);
iteration.setNextPartialSolution(stepFunction);
iteration.setMaximumNumberOfIterations(100); // or setTerminationCriterion(...)
iteration.validate(); // ok
Defensive patterns

Strategy: validation

Validate before calling

void validateBeforeExecute(BulkIterationBase<?> iter) {
    boolean hasTermination = iter.getTerminationCriterion() != null
        || iter.getMaximumNumberOfIterations() > 0;
    if (!hasTermination) {
        throw new IllegalStateException(
            "Iteration needs either setMaximumNumberOfIterations(n>=1) or setTerminationCriterion(...)");
    }
    iter.validate();
}

Type guard

boolean hasTerminationCondition(BulkIterationBase<?> iter) {
    return iter.getTerminationCriterion() != null || iter.getMaximumNumberOfIterations() >= 1;
}

Try / catch

try {
    iteration.validate();
} catch (InvalidProgramException e) {
    if (e.getMessage().contains("termination condition")) {
        iteration.setMaximumNumberOfIterations(DEFAULT_MAX_ITERATIONS);
        iteration.validate();
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Creating a BulkIterationBase, setting input and step function, but forgetting to call both setMaximumNumberOfIterations() and setTerminationCriterion(). Calling validate() on an incompletely configured iteration.

Common situations: Building an iteration and forgetting to specify how it terminates. Intending to use a convergence-based termination but not wiring the termination criterion operator. Refactoring that removes the iteration count or termination criterion without updating validation.

Related errors


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