flowable/flowable-engine · error · FlowableException
Unable to resolve formFieldValidationExpression to boolean v
Error message
Unable to resolve formFieldValidationExpression to boolean value for ${variableContainer} What it means
TaskHelper.isFormFieldValidationEnabled evaluates the formFieldValidationExpression via the expression manager and requires the result to be a boolean (per getBoolean coercion). If the expression evaluates to something that cannot be interpreted as a Boolean (getBoolean returns null, e.g. a number or arbitrary object), this FlowableException is thrown because the engine cannot decide whether form field validation is on.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/task/TaskHelper.java:271
taskServiceConfiguration.getInternalHistoryTaskManager().recordHistoryUserTaskLog(taskLogEntryBuilder);
}
}
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);View on GitHub (pinned to d6d39ce1c6)
Solutions
- Fix the expression so it evaluates to a real boolean, e.g. ${userInputRequired == true} or ${someFlag}, not ${someFlagValue} returning a String/number
- Ensure all variables referenced by the expression are set on the variableContainer before the task form is processed
- Test the expression with a known variable set (e.g. via a small unit test using FlowableExpressionTestUtil or equivalent) to confirm it yields Boolean true/false
- If the value can legitimately be non-boolean, sanitize it beforehand and pass a boolean variable to the expression
Example fix
// before
cmmn:formFieldValidationExpression="${validationLevel}"
// after
cmmn:formFieldValidationExpression="${validationLevel > 0}" Defensive patterns
Strategy: validation
Validate before calling
Object v = expressionValue(formFieldValidationExpression, variableContainer);
if (!(v instanceof Boolean) && !("true".equalsIgnoreCase(String.valueOf(v)) || "false".equalsIgnoreCase(String.valueOf(v)))) {
throw new IllegalStateException("formFieldValidationExpression must be boolean, got: " + v);
} Type guard
boolean isBooleanLike(Object v) { return v instanceof Boolean || "true".equalsIgnoreCase(String.valueOf(v)) || "false".equalsIgnoreCase(String.valueOf(v)); } Try / catch
try { enabled = TaskHelper.isFormFieldValidationEnabled(cfg, expr, container); } catch (FlowableException e) { if (e.getMessage().startsWith("Unable to resolve formFieldValidationExpression")) { log.error("Non-boolean validation expression: {}", expr); enabled = true; } else throw e; } Prevention
- Write validation expressions as explicit comparisons (x == true)
- Ensure referenced variables are initialized before form processing
- Unit-test expressions against expected variable types
When it happens
Trigger: A CMMN task/case definition sets cmmn:formFieldValidationExpression to an expression returning a non-boolean (e.g. a string other than 'true'/'false' handled by a stricter path, a number, or null result) while a variableContainer is present; the task then renders/validates its form.
Common situations: Typo in the expression returning e.g. 'yes'/'1' or an integer; expression referencing a missing variable yielding null; copying a validation expression pattern from a place where strings are coerced differently.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unable to resolve formFieldValidationExpression without vari
- scopeContainer cannot be null
- Expression condition ${condition} did not evaluate to a bool
- Unable to resolve formFieldValidationExpression to boolean v
- Unable to resolve formFieldValidationExpression without vari
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/bc2c65a00375b8cd.
Report an issue: GitHub.