{"record":{"id":"745deef74b3a8290","repo":"flowable/flowable-engine","slug":"endor-can-only-be-called-after-calling-or-745dee","errorCode":null,"errorMessage":"endOr() can only be called after calling or()","messagePattern":"endOr\\(\\) can only be called after calling or\\(\\)","errorType":"validation","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java","lineNumber":2082,"sourceCode":"    public HistoricTaskInstanceQuery or() {\n        if (inOrStatement) {\n            throw new FlowableException(\"the query is already in an or statement\");\n        }\n\n        inOrStatement = true;\n        if (databaseType != null) {\n            currentOrQueryObject = new HistoricTaskInstanceQueryImpl(commandExecutor, databaseType, taskServiceConfiguration, variableServiceConfiguration);\n        } else {\n            currentOrQueryObject = new HistoricTaskInstanceQueryImpl(commandExecutor, taskServiceConfiguration, variableServiceConfiguration);\n        }\n        orQueryObjects.add(currentOrQueryObject);\n        return this;\n    }\n\n    @Override\n    public HistoricTaskInstanceQuery endOr() {\n        if (!inOrStatement) {\n            throw new FlowableException(\"endOr() can only be called after calling or()\");\n        }\n\n        inOrStatement = false;\n        currentOrQueryObject = null;\n        return this;\n    }\n\n    // ordering\n    // /////////////////////////////////////////////////////////////////\n\n    @Override\n    public HistoricTaskInstanceQueryImpl orderByTaskId() {\n        orderBy(HistoricTaskInstanceQueryProperty.HISTORIC_TASK_INSTANCE_ID);\n        return this;\n    }\n\n    @Override\n    public HistoricTaskInstanceQueryImpl orderByHistoricActivityInstanceId() {","sourceCodeStart":2064,"sourceCodeEnd":2100,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-task-service/src/main/java/org/flowable/task/service/impl/HistoricTaskInstanceQueryImpl.java#L2064-L2100","documentation":"Flowable throws this FlowableException when HistoricTaskInstanceQuery.endOr() is called while no or-block is open (or() was never called, or endOr() was already called once). endOr() only closes an existing or-group, so calling it standalone is invalid query usage. It fails fast at query-construction time.","triggerScenarios":"Calling query.endOr() without a preceding query.or(), or calling endOr() twice after a single or().","commonSituations":"Dynamic query builders that unconditionally append endOr(); refactoring that removed the or() call but left endOr(); method chains assembled from optional fragments where the fragment containing or() was skipped.","solutions":["Only call endOr() when a matching or() was called earlier in the chain.","Make or()/endOr() calls paired in your builder code (e.g. always emit both together or neither).","If no or-group is needed, remove the endOr() call entirely.","Log/inspect the full query chain to find the unbalanced or()/endOr() pair."],"exampleFix":"// before\nquery.taskAssignee(\"john\").endOr(); // throws\n// after\nquery.taskAssignee(\"john\"); // no or-block, no endOr()","handlingStrategy":"validation","validationCode":"boolean useOr = needOrGroup();\nif (useOr) {\n    query.or();\n}\n// ... filters ...\nif (useOr) {\n    query.endOr();\n}","typeGuard":null,"tryCatchPattern":"try {\n    query.endOr();\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"endOr() can only be called\")) {\n        throw new IllegalStateException(\"Query builder misuse: endOr() without matching or()\", e);\n    }\n    throw e;\n}","preventionTips":["Track or-block state in your builder helper and emit endOr() only when a block is open","Never append endOr() unconditionally in dynamic query assembly","Keep or()/endOr() calls adjacent so mismatches are visible in code review","Add a test that executes every assembled query to surface imbalance"],"tags":["flowable","query-builder","or-statement","invalid-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}