flowable/flowable-engine · error · FlowableException
No UserTask instance found for " + taskEntity
Error message
No UserTask instance found for " + taskEntity
What it means
InjectParallelUserTaskCmd.updateBpmnProcess() fetches the task by taskId, resolves its current flow element in the process model, and requires it to be a UserTask. If the resolved FlowElement is a different element type (service task, receive task, sub process, etc.) it throws FlowableException 'No UserTask instance found for <taskEntity>', because parallel user task injection is only valid at user task positions.
Solutions
- Verify the current flow element for the task's taskDefinitionKey is a UserTask before invoking the injection API.
- Pick a task id for an actual user task (query taskService.createTaskQuery().taskCandidateGroup... etc.) rather than an arbitrary active execution.
- Re-deploy or correct the process definition if the task definition key mapping changed after a model update.
- Catch FlowableException and fall back to a different injection point.
Example fix
// before
processInstanceModification.injectParallelUserTask(nonUserTaskId, builder);
// after
TaskInfo task = taskService.createTaskQuery().taskId(taskId).singleResult();
FlowElement el = process.getFlowElement(task.getTaskDefinitionKey(), true);
if (el instanceof UserTask) {
processInstanceModification.injectParallelUserTask(taskId, builder);
} Defensive patterns
Strategy: validation
Validate before calling
FlowElement el = process.getFlowElement(task.getTaskDefinitionKey(), true);
if (!(el instanceof UserTask)) {
throw new IllegalArgumentException("Injection point is not a UserTask: " + task.getTaskDefinitionKey());
} Type guard
boolean isUserTaskElement(FlowElement el) { return el instanceof UserTask; } Try / catch
try {
modificationBuilder.injectParallelUserTask(taskId, builder);
} catch (FlowableException e) {
if (e.getMessage().startsWith("No UserTask instance found")) {
log.warn("Cannot inject parallel user task at non-user-task element for task {}", taskId);
}
throw e;
} Prevention
- Pick injection points only at user task executions
- Re-validate task definition keys after redeploying changed process definitions
- Query active user tasks explicitly before injecting
When it happens
Trigger: Calling the dynamic injection API (DynamicBpmnService / process instance modification) with a taskId whose underlying taskDefinitionKey resolves to a non-UserTask flow element in the deployed BpmnModel.
Common situations: Injecting after the process definition changed so the task definition key now maps to a different element; passing an id of a task that is actually inside a service task loop; assuming the active element at any execution point is a user task.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Could not find a none start event in dynamic sub process…
- No startFormHandler defined in process definition '
- The new process definition
- A channel key detection value is required for inbound…
- A channel key detection value is required for the channel…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/527ce813aaae8d42.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/InjectParallelUserTaskCmd.java:69
this.dynamicUserTaskBuilder = dynamicUserTaskBuilder;
}
@Override
public Void execute(CommandContext commandContext) {
createDerivedProcessDefinitionForTask(commandContext, taskId);
return null;
}
@Override
protected void updateBpmnProcess(CommandContext commandContext, Process process,
BpmnModel bpmnModel, ProcessDefinitionEntity originalProcessDefinitionEntity, DeploymentEntity newDeploymentEntity) {
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
TaskEntity taskEntity = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);
FlowElement flowElement = process.getFlowElement(taskEntity.getTaskDefinitionKey(), true);
if (!(flowElement instanceof UserTask userTask)) {
throw new FlowableException("No UserTask instance found for " + taskEntity);
}
SubProcess subProcess = new SubProcess();
String subProcessId = dynamicUserTaskBuilder.nextSubProcessId(process.getFlowElementMap());
subProcess.setId(subProcessId);
subProcess.setName(flowElement.getName());
for (SequenceFlow incomingFlow : userTask.getIncomingFlows()) {
incomingFlow.setTargetRef(subProcess.getId());
}
subProcess.setIncomingFlows(userTask.getIncomingFlows());
for (SequenceFlow outgoingFlow : userTask.getOutgoingFlows()) {
outgoingFlow.setSourceRef(subProcess.getId());
}
subProcess.setOutgoingFlows(userTask.getOutgoingFlows());
userTask.setIncomingFlows(new ArrayList<>());
View on GitHub (pinned to d6d39ce1c6)