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

  1. Ensure the variable used in the calledElement expression is set on the process instance before invoking change-state
  2. Simplify or fix the expression syntax in the BPMN callActivity definition
  3. 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

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


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)