{"record":{"id":"de098487f4c566db","repo":"flowable/flowable-engine","slug":"could-not-resolve-key-from-expression-eventtype","errorCode":null,"errorMessage":"Could not resolve key from expression: {eventType}","messagePattern":"Could not resolve key from expression: (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/agenda/operation/AbstractMovePlanItemInstanceToTerminalStateOperation.java","lineNumber":207,"sourceCode":"        }\n    }\n\n    protected boolean isAsyncLeave(PlanItemInstanceEntity planItemInstanceEntity, PlanItemDefinition planItemDefinition) {\n        return !PlanItemInstanceState.ASYNC_ACTIVE_LEAVE.equals(planItemInstanceEntity.getState())\n                && StateTransition.isPossible(planItemInstanceEntity, PlanItemTransition.ASYNC_LEAVE_ACTIVE)\n                && planItemDefinition instanceof Task && ((Task) planItemDefinition).isAsyncLeave();\n    }\n\n    protected VariableAggregationDefinitions getVariableAggregations() {\n        RepetitionRule repetitionRule = ExpressionUtil.getRepetitionRule(planItemInstanceEntity);\n        return repetitionRule != null ? repetitionRule.getAggregations() : null;\n    }\n    \n    protected String resolveEventDefinitionKey(String eventType, PlanItemInstanceEntity planItemInstanceEntity, CmmnEngineConfiguration cmmnEngineConfiguration) {\n        Object key = cmmnEngineConfiguration.getExpressionManager().createExpression(eventType).getValue(planItemInstanceEntity);\n\n        if (key == null) {\n            throw new FlowableException(\"Could not resolve key from expression: \" + eventType);\n        }\n\n        return key.toString();\n    }\n\n    /**\n     * Implementing classes should be aware that unlike extending from AbstractChangePlanItemInstanceStateOperation, this\n     * method will be executed just before the deleting the entity\n     */\n    @Override\n    protected abstract void internalExecute();\n    \n    public boolean isRepeatingOnDelete(String originalState, String newState) {\n        \n        // If there are no entry criteria and the repetition rule evaluates to true: a new instance needs to be created.\n\n        CaseInstanceEntity caseInstance = CommandContextUtil.getCaseInstanceEntityManager(commandContext).findById(planItemInstanceEntity.getCaseInstanceId());\n        if (CaseInstanceState.isInTerminalState(caseInstance)) {","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/agenda/operation/AbstractMovePlanItemInstanceToTerminalStateOperation.java#L189-L225","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: plan item eventType = \"{eventTypeName}\" but variable never set\ncaseInstance = cmmnRuntimeService.createCaseInstanceBuilder()\n    .variable(\"eventTypeName\", \"myEvent\")\n    .start();\n// after: variable guaranteed present before listener evaluation","handlingStrategy":"validation","validationCode":"// java\nObject v = runtimeService.getVariable(caseInstanceId, \"eventTypeName\");\nif (v == null) throw new IllegalStateException(\"Variable for eventType expression is not set\");","typeGuard":null,"tryCatchPattern":"try {\n    cmmnRuntimeService.triggerPlanItemInstance(id);\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"Could not resolve key from expression\")) {\n        // fix variable and retry\n    }\n}","preventionTips":["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."],"tags":["cmmn","expression","configuration"],"backgroundTag":"missing-config-value","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}