flowable/flowable-engine · error · FlowableException

could not find element for activity id " + enableActivityId

Error message

could not find element for activity id " + enableActivityId

What it means

When re-enabling activities (move to an event subprocess / enable activity ids), each enableActivityId is looked up in the BpmnModel; if getFlowElement returns null the id does not exist in the model and the operation aborts.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java:664

        
        for (EnableActivityContainer enableActivityContainer : processInstanceChangeState.getEnableActivityContainers()) {
            if (enableActivityContainer.getActivityIds() != null && !enableActivityContainer.getActivityIds().isEmpty()) {
                BpmnModel bpmnModel = null;
                ExecutionEntity parentExecution = executionEntityManager.findById(processInstanceChangeState.getProcessInstanceId());
                if (processInstanceChangeState.getProcessDefinitionToMigrateTo() != null) {
                    bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstanceChangeState.getProcessDefinitionToMigrateTo().getId());
                    
                } else {
                    bpmnModel = ProcessDefinitionUtil.getBpmnModel(parentExecution.getProcessDefinitionId());
                }
                
                ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
                ProcessInstanceHelper processInstanceHelper = processEngineConfiguration.getProcessInstanceHelper();
                
                for (String enableActivityId : enableActivityContainer.getActivityIds()) {
                    FlowElement enableFlowElement = bpmnModel.getFlowElement(enableActivityId);
                    if (enableFlowElement == null) {
                        throw new FlowableException("could not find element for activity id " + enableActivityId);
                    }
                    
                    processInstanceHelper.processEventSubProcessStartEvent(enableFlowElement, parentExecution, processEngineConfiguration, commandContext);
                }
            }
        }
    }

    protected void processPendingEventSubProcessesStartEvents(ProcessInstanceChangeState processInstanceChangeState, CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        ProcessInstanceHelper processInstanceHelper = processEngineConfiguration.getProcessInstanceHelper();
        EventSubscriptionService eventSubscriptionService = processEngineConfiguration.getEventSubscriptionServiceConfiguration().getEventSubscriptionService();
        ManagementService managementService = processEngineConfiguration.getManagementService();

        for (Map.Entry<? extends StartEvent, ExecutionEntity> pendingStartEventEntry : processInstanceChangeState.getPendingEventSubProcessesStartEvents().entrySet()) {
            StartEvent startEvent = pendingStartEventEntry.getKey();
            ExecutionEntity parentExecution = pendingStartEventEntry.getValue();
            EventDefinition eventDefinition = startEvent.getEventDefinitions().isEmpty() ? null : startEvent.getEventDefinitions().get(0);

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Validate each enableActivityId against repositoryService.getBpmnModel(processDefinitionId).getFlowElement(id) before the call
  2. Correct the activity ids in the enable container to match the deployed BPMN
  3. Pin the correct process definition version so the ids exist in the resolved model

Example fix

// before
.enableActivity("errorStart_1") // not in model
// after
if (bpmnModel.getFlowElement("errorStartEvent1") != null) { builder.enableActivity("errorStartEvent1"); }
Defensive patterns

Strategy: validation

Validate before calling

BpmnModel model = repositoryService.getBpmnModel(procDefId);
for (String id : enableActivityIds) {
    if (model.getFlowElement(id) == null) throw new IllegalArgumentException("Unknown enable activity " + id);
}

Try / catch

try { builder.changeState(); } catch (FlowableException e) { if (e.getMessage().startsWith("could not find element for activity id")) { /* fix enable ids */ } else throw e; }

Prevention

When it happens

Trigger: moveActivityIdTo... with an enableActivityContainer whose activity ids are absent from the current process definition's BPMN model (typo, wrong definition version, or id from another process).

Common situations: Ids copied from a different process diagram; definition redeployed with renamed event-subprocess start activities; case-sensitive id mismatch.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/cefd432ab85721aa. Report an issue: GitHub.