flowable/flowable-engine · error · FlowableException

Unable to resolve formFieldValidationExpression without vari

Error message

Unable to resolve formFieldValidationExpression without variable container

What it means

TaskHelper.isFormFieldValidationEnabled requires a VariableContainer when a formFieldValidationExpression is present; without one the expression cannot be evaluated at all, so the helper throws this FlowableException. It indicates the caller asked to evaluate form validation config but supplied no context variables.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/task/TaskHelper.java:275

    public static boolean isFormFieldValidationEnabled(VariableContainer variableContainer,
        CmmnEngineConfiguration cmmnEngineConfiguration, String formFieldValidationExpression) {
        if (StringUtils.isNotEmpty(formFieldValidationExpression)) {
            Boolean formFieldValidation = getBoolean(formFieldValidationExpression);
            if (formFieldValidation != null) {
                return formFieldValidation;
            }

            if (variableContainer != null) {
                ExpressionManager expressionManager = cmmnEngineConfiguration.getExpressionManager();
                Boolean formFieldValidationValue = getBoolean(
                    expressionManager.createExpression(formFieldValidationExpression).getValue(variableContainer)
                );
                if (formFieldValidationValue == null) {
                    throw new FlowableException("Unable to resolve formFieldValidationExpression to boolean value for " + variableContainer);
                }
                return formFieldValidationValue;
            }
            throw new FlowableException("Unable to resolve formFieldValidationExpression without variable container");
        }
        return true;
    }
    
    protected static void bulkDeleteHistoricTaskInstances(Collection<String> taskIds, CmmnEngineConfiguration cmmnEngineConfiguration) {
        HistoricTaskService historicTaskService = cmmnEngineConfiguration.getTaskServiceConfiguration().getHistoricTaskService();
        
        List<String> subTaskIds = historicTaskService.findHistoricTaskIdsByParentTaskIds(taskIds);
        if (subTaskIds != null && !subTaskIds.isEmpty()) {
            bulkDeleteHistoricTaskInstances(subTaskIds, cmmnEngineConfiguration);
        }
        
        cmmnEngineConfiguration.getVariableServiceConfiguration().getHistoricVariableService().bulkDeleteHistoricVariableInstancesByTaskIds(taskIds);
        cmmnEngineConfiguration.getIdentityLinkServiceConfiguration().getHistoricIdentityLinkService().bulkDeleteHistoricIdentityLinksForTaskIds(taskIds);
        
        if (cmmnEngineConfiguration.isEnableEntityLinks()) {
            cmmnEngineConfiguration.getEntityLinkServiceConfiguration().getHistoricEntityLinkService()
                    .bulkDeleteHistoricEntityLinksForScopeTypeAndScopeIdsOrReferenceScopeIds(ScopeTypes.TASK, taskIds);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass the task's/case's VariableContainer (e.g. the DelegateTask, PlanItemInstanceEntity, or a VariableScopeAdapter) instead of null
  2. If no variables are available, don't set a formFieldValidationExpression (it defaults to validation enabled when expression is absent)
  3. Ensure form-info processing happens in a context where CommandContextUtil can supply the proper variable container
  4. Null-check and log before calling, failing fast with a clearer app-level error

Example fix

// before
boolean enabled = TaskHelper.isFormFieldValidationEnabled(config, formInfo.getValidationExpression(), null);
// after
VariableContainer container = new VariableScopeAdapter(planItemInstanceEntity);
boolean enabled = TaskHelper.isFormFieldValidationEnabled(config, formInfo.getValidationExpression(), container);
Defensive patterns

Strategy: validation

Validate before calling

if (validationExpression != null && variableContainer == null) {
    throw new IllegalArgumentException("formFieldValidationExpression set but no VariableContainer provided");
}

Type guard

null

Try / catch

try { return TaskHelper.isFormFieldValidationEnabled(cfg, expr, container); } catch (FlowableException e) { if (e.getMessage().equals("Unable to resolve formFieldValidationExpression without variable container")) { log.warn("Missing variable container for form validation"); return true; } throw e; }

Prevention

When it happens

Trigger: Calling isFormFieldValidationEnabled(cmmnEngineConfiguration, formFieldValidationExpression, null) — i.e. a non-null validation expression with a null variableContainer — typically when processing task form info outside a proper case/plan-item context.

Common situations: Custom form rendering code that resolves form info without loading the task's variables; historic/async paths where the variable container was dropped; calling the helper from a listener with an uninitialized container.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/49337694fcda2f9d. Report an issue: GitHub.