flowable/flowable-engine · error · FlowableException

is created by the process engine and should be completed vi

Error message

 is created by the process engine and should be completed via the process engine API

What it means

Thrown by CompleteTaskWithFormCmd when the task being completed with a form has a non-empty processInstanceId, i.e. it was created by the BPMN process engine. As with plain completeTask, the CMMN engine refuses to complete a task it does not own; form-based completion must go through the engine that created the task.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/CompleteTaskWithFormCmd.java:113

    public CompleteTaskWithFormCmd(String taskId, String formDefinitionId, String outcome, Map<String,
            Object> variables, Map<String, Object> variablesLocal, Map<String, Object> transientVariables, Map<String, Object> transientVariablesLocal) {
        this(taskId, formDefinitionId, outcome, variables, transientVariables);
        this.variablesLocal = variablesLocal;
        this.transientVariablesLocal = transientVariablesLocal;
    }
    
    public CompleteTaskWithFormCmd(String taskId, String formDefinitionId, String outcome, String userId,
            Map<String,Object> variables, Map<String, Object> variablesLocal, Map<String, Object> transientVariables, 
            Map<String, Object> transientVariablesLocal) {
        
        this(taskId, formDefinitionId, outcome, variables, variablesLocal, transientVariables, transientVariablesLocal);
        this.userId = userId;
    }

    @Override
    protected Void execute(CommandContext commandContext, TaskEntity task) {
        if (StringUtils.isNotEmpty(task.getProcessInstanceId())) {
            throw new FlowableException(task + " is created by the process engine and should be completed via the process engine API");
        }
        
        FormService formService = CommandContextUtil.getFormService(commandContext);
        if (formService == null) {
            throw new FlowableIllegalArgumentException("Form engine is not initialized");
        }

        CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
        FormRepositoryService formRepositoryService = CommandContextUtil.getFormRepositoryService(commandContext);
        FormInfo formInfo = formRepositoryService.getFormModelById(formDefinitionId);

        if (formInfo != null) {
            // validate input at first
            FormFieldHandler formFieldHandler = cmmnEngineConfiguration.getFormFieldHandler();
            if (isFormFieldValidationEnabled(task)) {
                formService.validateFormFields(task.getTaskDefinitionKey(), "humanTask", task.getScopeId(), 
                        task.getScopeDefinitionId(), ScopeTypes.CMMN, formInfo, variables);
            }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Check task.getProcessInstanceId() before form completion and route process tasks to the BPMN completeTaskWithForm/TaskService API.
  2. Split task queries by processInstanceId vs caseInstanceId so each engine handles its own tasks.
  3. Refactor the task inbox to hold a reference to the originating engine per task.

Example fix

// before
cmmnTaskService.completeTaskWithForm(taskId, formDefinitionId, outcome, variables);
// after
if (task.getProcessInstanceId() != null) {
    processTaskService.completeTaskWithForm(taskId, formDefinitionId, outcome, variables);
} else {
    cmmnTaskService.completeTaskWithForm(taskId, formDefinitionId, outcome, variables);
}
Defensive patterns

Strategy: validation

Validate before calling

org.flowable.task.api.Task t = taskService.createTaskQuery().taskId(taskId).singleResult();
if (t != null && t.getProcessInstanceId() != null) {
    processTaskService.completeTaskWithForm(taskId, formDefinitionId, outcome, variables);
} else {
    cmmnTaskService.completeTaskWithForm(taskId, formDefinitionId, outcome, variables);
}

Prevention

When it happens

Trigger: Calling CmmnTaskService.completeTaskWithForm(taskId, ...) on a task whose getProcessInstanceId() is not empty (a BPMN process user task).

Common situations: Generic task inbox completing both process and case tasks via the CMMN form API; migration from BPMN-only to CMMN code paths where task routing was not updated.

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


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