flowable/flowable-engine · error · FlowableException
Cannot resolve calledElement expression
Error message
Cannot resolve calledElement expression '${calledProcessDefKey}' of callActivity '${callActivityId}' What it means
When moving execution state into/out of a callActivity, the callActivity's calledElement may be an expression. If evaluating that expression against the current process instance throws a FlowableException, it is wrapped and rethrown with the callActivity id. The expression (often referencing a variable) failed to evaluate.
Solutions
- Ensure the variable used in the calledElement expression is set on the process instance before invoking change-state
- Simplify or fix the expression syntax in the BPMN callActivity definition
- Catch/inspect the wrapped cause (FlowableException e) for the root evaluation failure
Example fix
// before
calledElement="${targetProcess}" with targetProcess never set
// after
runtimeService.setVariable(piId, "targetProcess", "orderProcess");
builder.moveActivityIdTo(...).changeState(); Defensive patterns
Strategy: validation
Validate before calling
Object target = runtimeService.getVariable(piId, "targetProcess");
if (target == null) throw new IllegalStateException("calledElement variable missing for callActivity"); Try / catch
try { builder.changeState(); } catch (FlowableException e) { if (e.getMessage().contains("Cannot resolve calledElement expression")) { logger.warn("cause", e.getCause()); } else throw e; } Prevention
- Set all variables referenced by calledElement expressions before change-state
- Prefer static calledElement values where possible
- Log e.getCause() — the original expression failure is wrapped
When it happens
Trigger: callActivity with flowable:calledElement="${someVar}" where the variable is missing/null on the process instance, or the expression itself throws during evaluation while a move/change-state operation crosses the callActivity.
Common situations: Variable not set before the move operation; expression references a bean not present in the context; moving executions that pass a callActivity boundary without the variables the calledElement expression depends on.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Could not resolve key for
- decisionTableReferenceKey expression does not resolve to a…
- decisionTableReferenceKey expression resolves to an empty…
- Error evaluating juel script
- Error while evaluating expression:
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/e7587314ecea4bf3.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java:414
}
CallActivity callActivity = null;
if (bpmnModelToMigrateTo != null) {
callActivity = (CallActivity) resolveFlowElementFromBpmnModel(bpmnModelToMigrateTo, moveExecutionContainer.getCallActivityId());
} else {
callActivity = (CallActivity) resolveFlowElementFromBpmnModel(bpmnModel, moveExecutionContainer.getCallActivityId());
}
moveExecutionContainer.setCallActivity(callActivity);
ProcessDefinition callActivityProcessDefinition = ProcessDefinitionUtil.getProcessDefinition(processDefinitionIdOfCallActivity);
String tenantId = callActivityProcessDefinition.getTenantId();
Integer calledProcessVersion = moveExecutionContainer.getCallActivitySubProcessVersion();
String calledProcessDefKey = callActivity.getCalledElement();
if (isExpression(calledProcessDefKey)) {
try {
calledProcessDefKey = expressionManager.createExpression(calledProcessDefKey).getValue(firstExecution.getProcessInstance()).toString();
} catch (FlowableException e) {
throw new FlowableException("Cannot resolve calledElement expression '" + calledProcessDefKey + "' of callActivity '" + callActivity.getId() + "'", e);
}
}
moveExecutionContainer.setSubProcessDefKey(calledProcessDefKey);
ProcessDefinition subProcessDefinition = resolveProcessDefinition(calledProcessDefKey, calledProcessVersion, tenantId, commandContext);
BpmnModel subProcessModel = ProcessDefinitionUtil.getBpmnModel(subProcessDefinition.getId());
moveExecutionContainer.setSubProcessDefinition(subProcessDefinition);
moveExecutionContainer.setSubProcessModel(subProcessModel);
newFlowElement = resolveFlowElementFromBpmnModel(subProcessModel, activityId);
canContainerDirectMigrate = false;
} else {
// Get first execution to get process definition id
ExecutionEntity firstExecution = moveExecutionContainer.getExecutions().get(0);
BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(firstExecution.getProcessDefinitionId());
currentActivityId = firstExecution.getCurrentActivityId();
currentFlowElement = resolveFlowElementFromBpmnModel(bpmnModel, currentActivityId);
if (bpmnModelToMigrateTo != null) {View on GitHub (pinned to d6d39ce1c6)