{"record":{"id":"a905c94818e86451","repo":"apache/flink","slug":"no-termination-condition-is-set-neither-fix-numbe","errorCode":null,"errorMessage":"No termination condition is set (neither fix number of iteration nor termination criterion).","messagePattern":"No termination condition is set \\(neither fix number of iteration nor termination criterion\\)\\.","errorType":"exception","errorClass":"InvalidProgramException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/common/operators/base/BulkIterationBase.java","lineNumber":176,"sourceCode":"    @Override\n    public AggregatorRegistry getAggregators() {\n        return this.aggregators;\n    }\n\n    /**\n     * @throws InvalidProgramException\n     */\n    public void validate() throws InvalidProgramException {\n        if (this.input == null) {\n            throw new RuntimeException(\"Operator for initial partial solution is not set.\");\n        }\n        if (this.iterationResult == null) {\n            throw new InvalidProgramException(\n                    \"Operator producing the next version of the partial \"\n                            + \"solution (iteration result) is not set.\");\n        }\n        if (this.terminationCriterion == null && this.numberOfIterations <= 0) {\n            throw new InvalidProgramException(\n                    \"No termination condition is set \"\n                            + \"(neither fix number of iteration nor termination criterion).\");\n        }\n    }\n\n    /**\n     * The BulkIteration meta operator cannot have broadcast inputs.\n     *\n     * @return An empty map.\n     */\n    public Map<String, Operator<?>> getBroadcastInputs() {\n        return Collections.emptyMap();\n    }\n\n    /**\n     * The BulkIteration meta operator cannot have broadcast inputs. This method always throws an\n     * exception.\n     *","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/common/operators/base/BulkIterationBase.java#L158-L194","documentation":"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.","triggerScenarios":"Creating a BulkIterationBase, setting input and step function, but forgetting to call both setMaximumNumberOfIterations() and setTerminationCriterion(). Calling validate() on an incompletely configured iteration.","commonSituations":"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.","solutions":["Always call iteration.setMaximumNumberOfIterations(n) with n >= 1, or set a termination criterion via iteration.setTerminationCriterion(criterionOperator).","If using data-driven termination, call setTerminationCriterion with an operator that produces an empty dataset when converged.","Call validate() early in development to catch missing termination configuration before job submission."],"exampleFix":"// before\nBulkIterationBase<MyType> iteration = new BulkIterationBase<>(operatorInfo, \"my-iter\");\niteration.setInput(dataSource);\niteration.setNextPartialSolution(stepFunction);\n// no termination set\niteration.validate(); // throws\n\n// after\nBulkIterationBase<MyType> iteration = new BulkIterationBase<>(operatorInfo, \"my-iter\");\niteration.setInput(dataSource);\niteration.setNextPartialSolution(stepFunction);\niteration.setMaximumNumberOfIterations(100); // or setTerminationCriterion(...)\niteration.validate(); // ok","handlingStrategy":"validation","validationCode":"void validateBeforeExecute(BulkIterationBase<?> iter) {\n    boolean hasTermination = iter.getTerminationCriterion() != null\n        || iter.getMaximumNumberOfIterations() > 0;\n    if (!hasTermination) {\n        throw new IllegalStateException(\n            \"Iteration needs either setMaximumNumberOfIterations(n>=1) or setTerminationCriterion(...)\");\n    }\n    iter.validate();\n}","typeGuard":"boolean hasTerminationCondition(BulkIterationBase<?> iter) {\n    return iter.getTerminationCriterion() != null || iter.getMaximumNumberOfIterations() >= 1;\n}","tryCatchPattern":"try {\n    iteration.validate();\n} catch (InvalidProgramException e) {\n    if (e.getMessage().contains(\"termination condition\")) {\n        iteration.setMaximumNumberOfIterations(DEFAULT_MAX_ITERATIONS);\n        iteration.validate();\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always call setMaximumNumberOfIterations or setTerminationCriterion before validate.","Use a checklist: input, step function, and termination must all be configured.","Call validate() during development to catch incomplete iteration setups."],"tags":["bulk-iteration","validation","termination","invalid-program","dataset-api","flink-core"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}