flowable/flowable-engine · error · FlowableException
Could not resolve key from expression: {eventType}
Error message
Could not resolve key from expression: {eventType} What it means
Flowable's CMMN engine treats an event type string that starts with '{' as an expression. resolveEventDefinitionKey evaluates that expression against the plan item instance to obtain the event definition key; if the expression evaluates to null, the engine cannot route the event, so it throws a FlowableException.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/agenda/operation/AbstractMovePlanItemInstanceToTerminalStateOperation.java:207
}
}
protected boolean isAsyncLeave(PlanItemInstanceEntity planItemInstanceEntity, PlanItemDefinition planItemDefinition) {
return !PlanItemInstanceState.ASYNC_ACTIVE_LEAVE.equals(planItemInstanceEntity.getState())
&& StateTransition.isPossible(planItemInstanceEntity, PlanItemTransition.ASYNC_LEAVE_ACTIVE)
&& planItemDefinition instanceof Task && ((Task) planItemDefinition).isAsyncLeave();
}
protected VariableAggregationDefinitions getVariableAggregations() {
RepetitionRule repetitionRule = ExpressionUtil.getRepetitionRule(planItemInstanceEntity);
return repetitionRule != null ? repetitionRule.getAggregations() : null;
}
protected String resolveEventDefinitionKey(String eventType, PlanItemInstanceEntity planItemInstanceEntity, CmmnEngineConfiguration cmmnEngineConfiguration) {
Object key = cmmnEngineConfiguration.getExpressionManager().createExpression(eventType).getValue(planItemInstanceEntity);
if (key == null) {
throw new FlowableException("Could not resolve key from expression: " + eventType);
}
return key.toString();
}
/**
* Implementing classes should be aware that unlike extending from AbstractChangePlanItemInstanceStateOperation, this
* method will be executed just before the deleting the entity
*/
@Override
protected abstract void internalExecute();
public boolean isRepeatingOnDelete(String originalState, String newState) {
// If there are no entry criteria and the repetition rule evaluates to true: a new instance needs to be created.
CaseInstanceEntity caseInstance = CommandContextUtil.getCaseInstanceEntityManager(commandContext).findById(planItemInstanceEntity.getCaseInstanceId());
if (CaseInstanceState.isInTerminalState(caseInstance)) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Set the variable referenced by the expression on the case/plan item instance before the event is triggered (e.g. runtimeService.setVariable).
- Verify the expression syntax and variable name; correct typos (eventType vs event_type etc.).
- If the key should be a literal, remove the braces so the string is not treated as an expression.
- Add a null/empty guard in your own logic before triggering the event.
Example fix
// before: plan item eventType = "{eventTypeName}" but variable never set
caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
.variable("eventTypeName", "myEvent")
.start();
// after: variable guaranteed present before listener evaluation Defensive patterns
Strategy: validation
Validate before calling
// java
Object v = runtimeService.getVariable(caseInstanceId, "eventTypeName");
if (v == null) throw new IllegalStateException("Variable for eventType expression is not set"); Try / catch
try {
cmmnRuntimeService.triggerPlanItemInstance(id);
} catch (FlowableException e) {
if (e.getMessage().startsWith("Could not resolve key from expression")) {
// fix variable and retry
}
} Prevention
- Always set variables referenced by '{...}' eventType expressions before the event fires.
- Prefer literal event keys over expressions when the value is static.
- Add a start-up check that all referenced case variables exist.
When it happens
Trigger: Configuring a plan item's triggeredByEvent / event type as an expression like ${eventTypeVariable} where the variable does not exist (or is null) on the plan item instance's variable scope when the agenda operation runs.
Common situations: Typos in the variable name inside the expression; variable set on the case instance but consulted before initialization; event source deleted the variable before the event listener fires; using literal text inside braces instead of a real variable.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- Could not find an implementation of the org.flowable.cdi.imp
- Error converting process reference expression
- no SMTP host is configured for the default mail server
- no SMTP host is configured for the mail server for tenant {t
- The mail client provider is not an instance of DefaultMailCl
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/de098487f4c566db.
Report an issue: GitHub.