{"record":{"id":"7208c68d690c2322","repo":"flowable/flowable-engine","slug":"variable-operation-is-missing-for-variable-name","errorCode":null,"errorMessage":"Variable operation is missing for variable: ${name}","messagePattern":"Variable operation is missing for variable: (.+?)","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":409,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/planitem/PlanItemInstanceBaseResource.java","lineNumber":151,"sourceCode":"        if (queryRequest.getTenantId() != null) {\n            query.planItemInstanceTenantId(queryRequest.getTenantId());\n        }\n\n        if (Boolean.TRUE.equals(queryRequest.getWithoutTenantId())) {\n            query.planItemInstanceWithoutTenantId();\n        }\n        \n        if (restApiInterceptor != null) {\n            restApiInterceptor.accessPlanItemInstanceInfoWithQuery(query, queryRequest);\n        }\n\n        return paginateList(requestParams, queryRequest, query, \"createTime\", allowedSortProperties, restResponseFactory::createPlanItemInstanceResponseList);\n    }\n\n    protected void addVariables(PlanItemInstanceQuery planItemInstanceQuery, List<QueryVariable> variables, boolean isCase) {\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.getValue() == null) {\n                throw new FlowableIllegalArgumentException(\"Variable value is missing for variable: \" + variable.getName());\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 && variable.getVariableOperation() != QueryVariableOperation.EQUALS) {\n                throw new FlowableIllegalArgumentException(\"Value-only query (without a variable-name) is only supported when using 'equals' operation.\");\n            }\n\n            switch (variable.getVariableOperation()) {\n\n            case EQUALS:\n                if (nameLess) {","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/runtime/planitem/PlanItemInstanceBaseResource.java#L133-L169","documentation":"PlanItemInstanceBaseResource.addVariables validates each QueryVariable in a plan-item-instance query: if variableOperation is null it throws FlowableIllegalArgumentException naming the variable. The plan item query API requires each variable filter to declare an operation (equals, notEquals, greaterThan, like, etc.) because the operation determines how the value is bound to the SQL comparison.","triggerScenarios":"GET /cmmn-runtime/plan-item-instances?variable=amount,42 or a JSON query body omitting the 'operation' field for a variable filter; the operation key is misspelled or dropped by a client-side query builder.","commonSituations":"Query builders that serialize only name/value; hand-written URLs using the comma syntax where the operation segment was omitted; migration from another REST API where operations were implicit.","solutions":["Include the operation in the filter, e.g. ?variable=amount:equals:42 (name:operation:value).","If using a JSON query request, set \"operation\":\"equals\" (or another supported op) on each variable entry.","Fix client query-builder serialization so the operation field is never dropped.","Check the allowed operation names in QueryVariable (equals, notEquals, greaterThan, greaterThanOrEquals, lessThan, lessThanOrEquals, like, notLike)."],"exampleFix":"// before\nGET /cmmn-runtime/plan-item-instances?variable=amount,42\n// after\nGET /cmmn-runtime/plan-item-instances?variable=amount:equals:42","handlingStrategy":"validation","validationCode":"for (const v of variableFilters) {\n  if (!v.operation) throw new Error(`variable filter '${v.name}' missing operation (equals, greaterThan, like, ...)`);\n}","typeGuard":"function hasOperation(v) { return v && typeof v.operation === 'string' && v.operation.length > 0; }","tryCatchPattern":"try { api.queryPlanItemInstances(query); }\ncatch (FlowableIllegalArgumentException e) { if (String(e.getMessage()).startsWith('Variable operation is missing')) { repairQueryOperations(e); } else throw e; }","preventionTips":["Always emit name:operation:value triplets in variable= query parameters.","In JSON query bodies, set operation on every QueryVariable.","Whitelist supported operations in your query builder to catch typos early.","Add unit tests that serialize and deserialize variable filters round-trip."],"tags":["rest-api","query","variables","validation","cmmn"],"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-14T05:17:10.506Z"}