{"record":{"id":"88a7c50fc497dceb","repo":"flowable/flowable-engine","slug":"variable-value-is-missing-for-variable-88a7c5","errorCode":null,"errorMessage":"Variable value is missing for variable: ","messagePattern":"Variable value is missing for variable: ","errorType":"http","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/variable/HistoricVariableInstanceBaseResource.java","lineNumber":122,"sourceCode":"        HistoricVariableInstance varObject = historyService.createHistoricVariableInstanceQuery().id(varInstanceId).singleResult();\n\n        if (varObject == null) {\n            throw new FlowableObjectNotFoundException(\"Historic variable instance '\" + varInstanceId + \"' couldn't be found.\", VariableInstanceEntity.class);\n        } else {\n            if (restApiInterceptor != null) {\n                restApiInterceptor.accessHistoryVariableInfoById(varObject);\n            }\n            return restResponseFactory.createRestVariable(varObject.getVariableName(), varObject.getValue(), null, varInstanceId, CmmnRestResponseFactory.VARIABLE_HISTORY_VARINSTANCE, includeBinary);\n        }\n    }\n\n    protected void addVariables(HistoricVariableInstanceQuery variableInstanceQuery, 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.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) {\n                throw new FlowableIllegalArgumentException(\"Value-only query (without a variable-name) is not supported\");\n            }\n\n            switch (variable.getVariableOperation()) {\n\n            case EQUALS:\n                variableInstanceQuery.variableValueEquals(variable.getName(), actualValue);\n                break;\n\n            default:","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/variable/HistoricVariableInstanceBaseResource.java#L104-L140","documentation":"Thrown as FlowableIllegalArgumentException when a variable predicate in the historic variable instance query has a null value. Value is required because the operation (equals, like, greaterThan, ...) needs an operand to compare against; restResponseFactory.getVariableValue(variable) would otherwise have nothing to convert. The request is rejected with HTTP 400 before any query runs.","triggerScenarios":"Query filter entry {\"name\":\"priority\",\"operation\":\"equals\"} with no \"value\" key, or value explicitly null, on GET /cmmn-history/historic-variable-instances with a variables filter.","commonSituations":"Clients trying to express 'is null' queries — Flowable historic variable query predicates do not support null operands, so the value must be a concrete typed value; also occurs when optional UI fields are left empty and serialized as null instead of being dropped from the filter.","solutions":["Provide a concrete value for the predicate: {\"name\":\"priority\",\"operation\":\"equals\",\"value\":5}.","To find unset variables, query the list endpoint without that variable filter and check variableValue == null in results (or query by name only), instead of a null-value predicate.","Drop empty/blank filters client-side before building the query so no variable entry with null value is sent.","Ensure the value's JSON type matches the stored variable type so getVariableValue can deserialize it."],"exampleFix":"// before: 400 - value missing\n{\"variables\":[{\"name\":\"priority\",\"operation\":\"equals\"}]}\n\n// after\n{\"variables\":[{\"name\":\"priority\",\"operation\":\"equals\",\"value\":5}]}","handlingStrategy":"validation","validationCode":"if (variables.stream().anyMatch(v -> v.getValue() == null)) {\n    throw new IllegalArgumentException(\"variable filters cannot have null value; drop the filter instead\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    HistoricVariableInstanceListResponse r = query(variables);\n} catch (FlowableIllegalArgumentException e) {\n    // HTTP 400: null value in variable predicate\n}","preventionTips":["Omit empty/blank filters instead of serializing null values","Express 'unset variable' by listing and checking variableValue==null client-side","Ensure value JSON types match stored variable types"],"tags":["rest-api","query","validation","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-14T05:17:10.506Z"}