flowable/flowable-engine · error · ActivitiIllegalArgumentException

A process instance id is required, but the provided id '" +…

Error message

A process instance id is required, but the provided id '" + processInstanceId + "' points to a child execution of process instance '" + processInstance.getProcessInstanceId() + "'. Please invoke the " + getClass().getSimpleName() + " with a root execution id.

What it means

findExecutionById can return a child (concurrent or scope) execution rather than the root. Because the command must operate on the process instance as a whole, it checks isProcessInstanceType() and throws ActivitiIllegalArgumentException when the id points to a child execution, telling the caller to use the root execution id.

Solutions

  1. Use processInstance.getProcessInstanceId() (available on the child execution) as the id — that is always the root.
  2. Query with runtimeService.createProcessInstanceQuery().processInstanceId(...) instead of createExecutionQuery() to obtain root ids.
  3. In listeners, use delegateExecution.getProcessInstanceId(), not getExecutionId().

Example fix

// before
runtimeService.setProcessDefinitionVersion(execution.getId(), newVersion); // child execution
// after
runtimeService.setProcessDefinitionVersion(execution.getProcessInstanceId(), newVersion);
Defensive patterns

Strategy: validation

Validate before calling

String rootId = execution.isProcessInstanceType() ? execution.getId() : execution.getProcessInstanceId();

Type guard

boolean isRootExecution(Execution e) { return e.isProcessInstanceType(); }

Try / catch

try {
    runtimeService.setProcessDefinitionVersion(pid, version);
} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {
    // pid was a child execution; resolve root and retry
}

Prevention

When it happens

Trigger: Passing an execution id (e.g. from an ExecutionQuery, a task's executionId, or an event listener on a concurrent branch) into setProcessDefinitionVersion instead of the process instance id.

Common situations: Code that stores executionId from a DelegateExecution in a parallel/multi-instance branch and later uses it as an instance id; migration scripts iterating executions rather than process instances.

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/530f9454f22edf28. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SetProcessDefinitionVersionCmd.java:82

            throw new ActivitiIllegalArgumentException("The process definition version is mandatory, but 'null' has been provided.");
        }
        if (processDefinitionVersion < 1) {
            throw new ActivitiIllegalArgumentException("The process definition version must be positive, but '" + processDefinitionVersion + "' has been provided.");
        }
        this.processInstanceId = processInstanceId;
        this.processDefinitionVersion = processDefinitionVersion;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        // check that the new process definition is just another version of the same
        // process definition that the process instance is using
        ExecutionEntityManager executionManager = commandContext.getExecutionEntityManager();
        ExecutionEntity processInstance = executionManager.findExecutionById(processInstanceId);
        if (processInstance == null) {
            throw new ActivitiObjectNotFoundException("No process instance found for id = '" + processInstanceId + "'.", ProcessInstance.class);
        } else if (!processInstance.isProcessInstanceType()) {
            throw new ActivitiIllegalArgumentException(
                    "A process instance id is required, but the provided id " +
                            "'" + processInstanceId + "' " +
                            "points to a child execution of process instance " +
                            "'" + processInstance.getProcessInstanceId() + "'. " +
                            "Please invoke the " + getClass().getSimpleName() + " with a root execution id.");
        }
        ProcessDefinitionImpl currentProcessDefinitionImpl = processInstance.getProcessDefinition();

        DeploymentManager deploymentCache = commandContext
                .getProcessEngineConfiguration()
                .getDeploymentManager();
        ProcessDefinition currentProcessDefinition = null;
        if (currentProcessDefinitionImpl instanceof ProcessDefinitionEntity) {
            currentProcessDefinition = (ProcessDefinitionEntity) currentProcessDefinitionImpl;
        } else {
            currentProcessDefinition = deploymentCache.findDeployedProcessDefinitionById(currentProcessDefinitionImpl.getId());
        }

View on GitHub (pinned to d6d39ce1c6)