flowable/flowable-engine · error · FlowableException

No UserTask instance found for task definition key " +…

Error message

No UserTask instance found for task definition key " + taskEntity.getTaskDefinitionKey()

What it means

Thrown by DynamicSubProcessJoinInjectUtil.injectSubProcessWithJoin when dynamically injecting an embedded subprocess at a running task: the task identified by taskId does not resolve to a UserTask flow element in the process model. The injection algorithm anchors the new subprocess around a user task, so any other element type (service task, gateway, etc.) is rejected.

Solutions

  1. Pass the taskId of an active UserTask whose task definition key exists as a UserTask in the current process definition
  2. Verify process.getFlowElement(taskEntity.getTaskDefinitionKey(), true) resolves to a UserTask in the deployed BPMN
  3. Redeploy or reference the correct process definition if the model and runtime are out of sync
  4. Use an injection API suited to non-user-task anchors instead of the join-injection utility

Example fix

// before
injectSubProcessWithJoin(serviceTaskTaskId, builder, ...); // service task, fails
// after
Task task = taskService.createTaskQuery().taskCandidateUser(user).singleResult(); // must be a UserTask
injectSubProcessWithJoin(task.getId(), builder, ...);
Defensive patterns

Strategy: validation

Validate before calling

Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
FlowElement el = process.getFlowElement(task.getTaskDefinitionKey(), true);
if (!(el instanceof UserTask)) throw new IllegalArgumentException("taskId must anchor on a UserTask");

Type guard

static boolean isUserTaskAnchor(Process process, TaskEntity task) {
    return process.getFlowElement(task.getTaskDefinitionKey(), true) instanceof UserTask;
}

Try / catch

try {
    injectSubProcessWithJoin(taskId, builder, process, bpmnModel, def, deployment, commandContext);
} catch (FlowableException ex) {
    if (ex.getMessage().startsWith("No UserTask instance found")) {
        // pick a UserTask-anchored taskId
    } else throw ex;
}

Prevention

When it happens

Trigger: Calling DynamicBpmnService-style dynamic injection (injectSubProcessWithJoin) with a taskId whose task definition key points at a non-UserTask element, or a task definition key that is missing/stale in the process model (getFlowElement returns null or another FlowElement).

Common situations: Passing a standalone-task id that has no matching activity in the model; the process definition was changed so the task definition key no longer maps to the UserTask; injecting at an automatically executed task instead of a user task.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/DynamicSubProcessJoinInjectUtil.java:56

import org.flowable.engine.impl.persistence.entity.ResourceEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.impl.util.ProcessDefinitionUtil;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;

/**
 * @author Tijs Rademakers
 */
public class DynamicSubProcessJoinInjectUtil extends BaseDynamicSubProcessInjectUtil {
    
    public static void injectSubProcessWithJoin(String taskId, Process process, BpmnModel bpmnModel, DynamicEmbeddedSubProcessBuilder dynamicEmbeddedSubProcessBuilder,
                    ProcessDefinitionEntity originalProcessDefinitionEntity, DeploymentEntity newDeploymentEntity, CommandContext commandContext) {
        
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        TaskEntity taskEntity = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);
        FlowElement taskFlowElement = process.getFlowElement(taskEntity.getTaskDefinitionKey(), true);
        if (!(taskFlowElement instanceof UserTask userTask)) {
            throw new FlowableException("No UserTask instance found for task definition key " + taskEntity.getTaskDefinitionKey());
        }

        if (dynamicEmbeddedSubProcessBuilder.getId() != null && process.getFlowElement(dynamicEmbeddedSubProcessBuilder.getId(), true) != null) {
            throw new FlowableIllegalArgumentException("Invalid sub-process identifier: identifier already exists in host process definition");
        }
        
        GraphicInfo elementGraphicInfo = bpmnModel.getGraphicInfo(userTask.getId());
        
        SubProcess parentSubProcess = new SubProcess();
        String subProcessId = dynamicEmbeddedSubProcessBuilder.nextSubProcessId(process.getFlowElementMap());
        parentSubProcess.setId(subProcessId);
        parentSubProcess.setName(userTask.getName());
        
        for (SequenceFlow incomingFlow : userTask.getIncomingFlows()) {
            incomingFlow.setTargetRef(parentSubProcess.getId());
        }
        parentSubProcess.setIncomingFlows(userTask.getIncomingFlows());
        

View on GitHub (pinned to d6d39ce1c6)