{"record":{"id":"3b2272958fa3e8b4","repo":"flowable/flowable-engine","slug":"variable-operation-is-missing-for-variable-va-3b2272","errorCode":null,"errorMessage":"Variable operation is missing for variable: \" + variable.getName()","messagePattern":"Variable operation is missing for variable: \" \\+ variable\\.getName\\(\\)","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricTaskInstanceBaseResource.java","lineNumber":344,"sourceCode":"    }\n\n    /**\n     * Returns the {@link HistoricTaskInstance} that is requested without calling the access interceptor\n     * Throws the right exceptions when bad request was made or instance was not found.\n     */\n    protected HistoricTaskInstance getHistoricTaskInstanceFromRequestWithoutAccessCheck(String taskId) {\n        HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();\n        if (taskInstance == null) {\n            throw new FlowableObjectNotFoundException(\"Could not find a task instance with id '\" + taskId + \"'.\", HistoricTaskInstance.class);\n        }\n        \n        return taskInstance;\n    }\n\n    protected void addTaskVariables(HistoricTaskInstanceQuery taskInstanceQuery, List<QueryVariable> variables) {\n        for (QueryVariable variable : variables) {\n            if (variable.getVariableOperation() == null) {\n                throw new FlowableIllegalArgumentException(\"Variable operation is missing for variable: \" + variable.getName());\n            }\n            if (variable.getVariableOperation() != QueryVariableOperation.EXISTS && variable.getVariableOperation() != QueryVariableOperation.NOT_EXISTS) {\n                if (variable.getValue() == null) {\n                    throw new FlowableIllegalArgumentException(\"Variable value is missing for variable: \" + variable.getName());\n                }\n            }\n\n            boolean nameLess = variable.getName() == null;\n\n            Object actualValue = restResponseFactory.getVariableValue(variable);\n\n            // A value-only query is only possible using equals-operator\n            if (nameLess) {\n                throw new FlowableIllegalArgumentException(\"Value-only query (without a variable-name) is not supported.\");\n            }\n\n            switch (variable.getVariableOperation()) {\n","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/history/HistoricTaskInstanceBaseResource.java#L326-L362","documentation":"When building variable filters for a historic task instance query, each QueryVariable must declare a variableOperation. If it is null Flowable throws FlowableIllegalArgumentException because the query cannot know how to compare the variable. This is pure client request validation, thrown before any query executes.","triggerScenarios":"POST query on /history/historic-tasks with a 'taskVariables' (or variables) entry whose 'operation' field is missing or misspelled (e.g. 'op' instead of 'operation'), producing addTaskVariables with a null operation.","commonSituations":"JSON body omits the operation property; client passes an operation string not mapped to QueryVariableOperation so the enum stays null; hand-built QueryVariable objects without setVariableOperation.","solutions":["Set a valid operation on each variable filter, e.g. {\"name\":\"x\",\"operation\":\"equals\",\"value\":1}","Check the operation string against the supported QueryVariableOperation values (equals, notEquals, equalsIgnoreCase, like, greaterThan, exists, etc.)","Fix field name in the JSON payload so it deserializes into variableOperation"],"exampleFix":"// before\n{\"taskVariables\":[{\"name\":\"priority\",\"value\":5}]}\n// after\n{\"taskVariables\":[{\"name\":\"priority\",\"operation\":\"equals\",\"value\":5}]}","handlingStrategy":"validation","validationCode":"for (QueryVariable v : variables) {\n    if (v.getVariableOperation() == null)\n        throw new IllegalArgumentException(\"operation required for variable \" + v.getName());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include the 'operation' field in variable filter JSON","Use the supported operation names from QueryVariableOperation","Validate request bodies before posting to query endpoints"],"tags":["rest-api","validation","query-variables","flowable"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}