flowable/flowable-engine · error · FlowableException

The is created by the cmmn engine and should be completed…

Error message

The  is created by the cmmn engine and should be completed via the cmmn engine API

What it means

CompleteTaskWithFormCmd refuses to complete a task that was created by the CMMN engine. Such tasks are owned and lifecycle-managed by the CMMN engine, so completing them through the process (BPMN) task-form API would bypass CMMN state management. The library throws a plain FlowableException to force callers onto the correct engine API.

Solutions

  1. Check task.getScopeType() before completing; if it is 'cmmn', call the CMMN engine API instead: CmmnTaskService.completeTaskWithForm(taskId, formDefinitionId, formOutcome, variables).
  2. Inspect the task (taskService.createTaskQuery().taskId(id).singleResult()) to see scopeType/scopeId and route to the proper service programmatically.
  3. If the task should not be a CMMN task, fix the deployment: it was started from a case definition, not a process definition.

Example fix

// before
taskService.completeTaskWithForm(taskId, formId, outcome, vars);
// after
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (ScopeTypes.CMMN.equals(task.getScopeType())) {
    cmmnTaskService.completeTaskWithForm(taskId, formId, outcome, vars);
} else {
    taskService.completeTaskWithForm(taskId, formId, outcome, vars);
}
Defensive patterns

Strategy: type-guard

Validate before calling

Task t = taskService.createTaskQuery().taskId(taskId).singleResult();
boolean isCmmnTask = t != null && "cmmn".equals(t.getScopeType());
if (isCmmnTask) { /* route to cmmnTaskService.completeTaskWithForm(...) */ }

Type guard

boolean isCmmnTask(Task t) { return t != null && ScopeTypes.CMMN.equals(t.getScopeType()); }

Try / catch

try {
    taskService.completeTaskWithForm(taskId, formId, outcome, vars);
} catch (FlowableException e) {
    if (e.getMessage().contains("cmmn engine")) {
        cmmnTaskService.completeTaskWithForm(taskId, formId, outcome, vars);
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling TaskService.completeTaskWithForm (or the CompleteTaskWithFormCmd command directly) on a TaskEntity whose scopeId is set and whose scopeType equals ScopeTypes.CMMN, i.e. a task originating from a CMMN case rather than a BPMN process.

Common situations: Applications that mix BPMN processes and CMMN cases and use a generic 'complete task with form' endpoint keyed only by taskId; after migration to Flowable 6 where CMMN-managed tasks appear in the same task queries as BPMN tasks; UI task lists that do not distinguish task scope.

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/9625678074d68de8. Report an issue: GitHub.

Appendix: source

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

            Object> variables, Map<String, Object> variablesLocal, Map<String, Object> transientVariables, Map<String, Object> transientVariablesLocal) {
        this(taskId, formDefinitionId, outcome, variables);
        this.variablesLocal = variablesLocal;
        this.transientVariables = transientVariables;
        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.getScopeId()) && ScopeTypes.CMMN.equals(task.getScopeType())) {
            throw new FlowableException("The " + task + " is created by the cmmn engine and should be completed via the cmmn engine API");
        }
        
        FormService formService = CommandContextUtil.getFormService();
        if (formService == null) {
            throw new FlowableIllegalArgumentException("Form engine is not initialized");
        }

        FormRepositoryService formRepositoryService = CommandContextUtil.getFormRepositoryService();
        FormInfo formInfo = formRepositoryService.getFormModelById(formDefinitionId);

        Map<String, Object> formVariables;
        boolean local = variablesLocal != null && !variablesLocal.isEmpty();
        if (local) {
            formVariables = variablesLocal;
        } else {
            formVariables = variables;
        }
        Map<String, Object> taskVariables = null;

View on GitHub (pinned to d6d39ce1c6)