{"record":{"id":"aadc1c0fd0fac87b","repo":"flowable/flowable-engine","slug":"no-channel-keys-configured-for-execution","errorCode":null,"errorMessage":"No channel keys configured for ${execution}","messagePattern":"No channel keys configured for (.+?)","errorType":"validation","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/SendEventTaskActivityBehavior.java","lineNumber":211,"sourceCode":"                            } else {\n                                throw new FlowableIllegalArgumentException(\"Can only use a collection of String elements for referencing channel model key\");\n\n                            }\n                        }\n\n                    } else if (resolvedChannelKey instanceof String) {\n                        String[] keys = ((String) resolvedChannelKey).split(\",\");\n                        channelKeys.addAll(Arrays.asList(keys));\n\n                    }\n                }\n            }\n        }\n\n        if (channelKeys.isEmpty()) {\n            if (!sendOnSystemChannel) {\n                // If the event is going to be send on the system channel then it is allowed to not define any other channels\n                throw new FlowableException(\"No channel keys configured for \" + execution);\n            } else {\n                return Collections.emptyList();\n            }\n        }\n\n        EventRepositoryService eventRepositoryService = CommandContextUtil.getEventRegistryEngineConfiguration(commandContext).getEventRepositoryService();\n        List<ChannelModel> channelModels = new ArrayList<>(channelKeys.size());\n        for (String channelKey : channelKeys) {\n            if (Objects.equals(ProcessEngineConfiguration.NO_TENANT_ID, execution.getTenantId())) {\n                channelModels.add(eventRepositoryService.getChannelModelByKey(channelKey));\n            } else {\n                channelModels.add(eventRepositoryService.getChannelModelByKey(channelKey, execution.getTenantId()));\n            }\n        }\n\n        return channelModels;\n    }\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/bpmn/behavior/SendEventTaskActivityBehavior.java#L193-L229","documentation":"SendEventTaskActivityBehavior.getChannelModels throws this when no channel keys could be resolved for the send event task and the event is not being sent on the system channel. Flowable requires at least one destination channel unless sendOnSystemChannel applies.","triggerScenarios":"The channelKey field/expression resolves to null or to an empty collection, and the execution is not on the system channel, so channelKeys.isEmpty() is true at the guard in getChannelModels.","commonSituations":"Forgetting to set the channelKey attribute on the send event task; an expression referencing a variable that was never set (resolves to null); a comma-split producing only blank entries that get filtered out.","solutions":["Add or correct the channelKey attribute on the send event task in the BPMN XML","Ensure the variable or bean referenced by the channelKey expression is populated before the task executes and non-empty","If the event should go through the platform's system channel, mark it as a system channel so the empty-list case is permitted","Verify the expression result after splitting on commas is not an array of empty strings"],"exampleFix":"// before\n<sendEvent eventType=\"orderShippedEvent\"/>  <!-- no channelKey -->\n// after\n<sendEvent eventType=\"orderShippedEvent\" channelKey=\"outboundOrderChannel\"/>","handlingStrategy":"validation","validationCode":"// Ensure channel keys are non-empty before executing the send event task\nObject channels = execution.getVariable(\"channels\");\nif (channels == null || (channels instanceof Collection && ((Collection<?>) channels).isEmpty())) {\n    throw new IllegalStateException(\"No channel keys configured for execution \" + execution.getId());\n}","typeGuard":null,"tryCatchPattern":"try {\n    processEngine.getRuntimeService().signal(executionId);\n} catch (FlowableException e) {\n    if (e.getMessage().startsWith(\"No channel keys configured\")) {\n        // set channelKey or mark event as system channel\n    }\n}","preventionTips":["Always set channelKey on send event tasks unless using the system channel","Validate channelKey expressions resolve non-null in a unit test","Trim/split comma lists and filter blanks before storing"],"tags":["event-registry","configuration","channel","flowable"],"backgroundTag":"missing-required-argument","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"}