{"record":{"id":"b4d102c97e1c7b80","repo":"flowable/flowable-engine","slug":"expression-jobtopicexpression-did-not-evaluate-b4d102","errorCode":null,"errorMessage":"Expression ${jobTopicExpression} did not evaluate to a valid value (non empty String). Was: ${topicValue}","messagePattern":"Expression (.+?) did not evaluate to a valid value \\(non empty String\\)\\. Was: (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ExternalWorkerTaskActivityBehavior.java","lineNumber":124,"sourceCode":"            job.setRetries(jobServiceConfiguration.getAsyncExecutorNumberOfRetries());\n\n            // Inherit tenant id (if applicable)\n            if (execution.getTenantId() != null) {\n                job.setTenantId(execution.getTenantId());\n            }\n\n            Expression jobTopicExpression;\n            if (StringUtils.isEmpty(beforeContext.getJobTopicExpression())) {\n                jobTopicExpression = this.jobTopicExpression;\n            } else {\n                jobTopicExpression = processEngineConfiguration.getExpressionManager()\n                        .createExpression(beforeContext.getJobTopicExpression());\n            }\n            Object topicValue = jobTopicExpression.getValue(execution);\n            if (topicValue != null && !topicValue.toString().isEmpty()) {\n                job.setJobHandlerConfiguration(topicValue.toString());\n            } else {\n                throw new FlowableException(\"Expression \" + jobTopicExpression + \" did not evaluate to a valid value (non empty String). Was: \" + topicValue);\n            }\n\n            jobService.insertExternalWorkerJob(job);\n\n            if (interceptor != null) {\n                interceptor.afterCreateExternalWorkerJob(new CreateExternalWorkerJobAfterContext(\n                        (ExternalWorkerServiceTask) currentFlowElement,\n                        job,\n                        execution\n                ));\n            }\n        } else {\n            leave((ActivityExecution) execution);\n        }\n    }\n\n    @Override\n    public void signal(ActivityExecution execution, String signalName, Object data) {","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/bpmn/behavior/ExternalWorkerTaskActivityBehavior.java#L106-L142","documentation":"ExternalWorkerTaskActivityBehavior.execute() evaluates the job's topic expression and sets it as the job handler configuration. If the expression returns null or an empty string, the external worker job would have no topic, so it throws FlowableException with the expression and the evaluated value.","triggerScenarios":"A service task of type 'external worker' has a flowable:topic expression that evaluates to null or \"\" at runtime, e.g. ${topicVar} where topicVar is unset.","commonSituations":"Topic variable never initialized before the task; expression referencing a misspelled variable; expression built from request data that was empty.","solutions":["Ensure the variable used in the topic expression is set with a non-empty value before the task executes","Use a literal topic string instead of an expression if the topic is static, e.g. flowable:topic=\"myTopic\"","Add a default in the expression, e.g. ${topicVar ?: 'defaultTopic'} (SpEL/UEL equivalent) or set it in an execution listener","Validate the input data feeding the topic variable at process start"],"exampleFix":"// before\n<serviceTask id=\"ext\" flowable:type=\"external-worker\" flowable:topic=\"${missingVar}\"/>\n// after\n<serviceTask id=\"ext\" flowable:type=\"external-worker\" flowable:topic=\"my-topic\"/>","handlingStrategy":"validation","validationCode":"Object topic = execution.getVariable(\"topicVar\");\nif (topic == null || topic.toString().isEmpty()) throw new IllegalStateException(\"topic must be non-empty before external worker task\");","typeGuard":null,"tryCatchPattern":"try { /* advance to external worker task */ }\ncatch (FlowableException e) { if (e.getMessage().contains(\"did not evaluate to a valid value\")) { fixTopicVariable(); } throw e; }","preventionTips":["Set topic variables before reaching the task (e.g. in an execution listener)","Use literal topics when the topic is static","Validate inputs at process start"],"tags":["bpmn","external-worker","expression","topic"],"backgroundTag":"invalid-expression-evaluation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}