{"record":{"id":"27d2fef5d8d1e0f6","repo":"flowable/flowable-engine","slug":"unable-to-resolve-formfieldvalidationexpression-wi-27d2fe","errorCode":null,"errorMessage":"Unable to resolve formFieldValidationExpression without variable container","messagePattern":"Unable to resolve formFieldValidationExpression without variable container","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/TaskHelper.java","lineNumber":701,"sourceCode":"            ProcessEngineConfigurationImpl processEngineConfiguration, String formFieldValidationExpression) {\n\n        if (StringUtils.isNotEmpty(formFieldValidationExpression)) {\n            Boolean formFieldValidation = getBoolean(formFieldValidationExpression);\n            if (formFieldValidation != null) {\n                return formFieldValidation;\n            }\n\n            if (variableContainer != null) {\n                ExpressionManager expressionManager = processEngineConfiguration.getExpressionManager();\n                Boolean formFieldValidationValue = getBoolean(\n                    expressionManager.createExpression(formFieldValidationExpression).getValue(variableContainer)\n                );\n                if (formFieldValidationValue == null) {\n                    throw new FlowableException(\"Unable to resolve formFieldValidationExpression to boolean value for \" + variableContainer);\n                }\n                return formFieldValidationValue;\n            }\n            throw new FlowableException(\"Unable to resolve formFieldValidationExpression without variable container\");\n        }\n        return true;\n    }\n    \n    protected static void bulkDeleteHistoricTaskInstances(Collection<String> taskIds, ProcessEngineConfigurationImpl processEngineConfiguration) {\n        HistoricTaskService historicTaskService = processEngineConfiguration.getTaskServiceConfiguration().getHistoricTaskService();\n        List<String> subTaskIds = historicTaskService.findHistoricTaskIdsByParentTaskIds(taskIds);\n        if (subTaskIds != null && !subTaskIds.isEmpty()) {\n            bulkDeleteHistoricTaskInstances(subTaskIds, processEngineConfiguration);\n        }\n        \n        processEngineConfiguration.getCommentEntityManager().bulkDeleteCommentsForTaskIds(taskIds);\n        processEngineConfiguration.getAttachmentEntityManager().bulkDeleteAttachmentsByTaskId(taskIds);\n        \n        processEngineConfiguration.getHistoricDetailEntityManager().bulkDeleteHistoricDetailsByTaskIds(taskIds);\n        processEngineConfiguration.getVariableServiceConfiguration().getHistoricVariableService().bulkDeleteHistoricVariableInstancesByTaskIds(taskIds);\n        processEngineConfiguration.getIdentityLinkServiceConfiguration().getHistoricIdentityLinkService().bulkDeleteHistoricIdentityLinksForTaskIds(taskIds);\n","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/util/TaskHelper.java#L683-L719","documentation":"TaskHelper throws this when a formFieldValidationExpression exists but there is no variableContainer available to evaluate it against. The engine cannot resolve a form validation expression without a variable context, so it refuses and defaults are not silently applied.","triggerScenarios":"Evaluating form field validation for a task definition that specifies formFieldValidationExpression, invoked through a code path where the passed variableContainer is null (e.g. no execution/scope variables available at that point).","commonSituations":"Calling internal APIs directly without passing the execution/variableScope; evaluating task form metadata outside a process context; unit tests that instantiate task helpers without a variable container.","solutions":["Provide a variable container: evaluate within the task's execution/scope context (e.g. pass the DelegateTask or ExecutionEntity variables).","Remove the formFieldValidationExpression from the task definition if validation is not context-dependent.","Guard the evaluation site so the helper is only called when variableContainer != null.","For out-of-context evaluation, supply a standalone VariableScope (e.g. a VariableScopeImpl populated with test variables)."],"exampleFix":"// before\ntaskHelper.evaluateFormFieldValidation(expression, null);\n// after\nif (variableContainer != null) {\n    taskHelper.evaluateFormFieldValidation(expression, variableContainer);\n} else {\n    throw new IllegalArgumentException(\"formFieldValidationExpression requires a variable container\");\n}","handlingStrategy":"validation","validationCode":"if (expr != null && variableContainer == null) throw new IllegalArgumentException(\"formFieldValidationExpression set but no variable container supplied\");","typeGuard":"boolean canEvaluateValidation(String expr, VariableScope vc) { return expr == null || vc != null; }","tryCatchPattern":"try { /* evaluate */ } catch (FlowableException e) { if (e.getMessage().contains(\"without variable container\")) { /* supply container or skip */ } else throw e; }","preventionTips":["Never call form-validation evaluation outside a variable scope context","Remove context-independent validation expressions from task definitions","Pass the DelegateTask/execution as the variable container in custom code"],"tags":["flowable","expression","form-validation","missing-required-argument"],"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"}