Activiti/Activiti · 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

The provided id exists but points to a child execution (a concurrent branch or scope) rather than the root process instance execution — ExecutionEntity.isProcessInstanceType() returned false. Activiti requires a root execution id for version switching, so it throws ActivitiIllegalArgumentException and tells you the parent process instance id to use instead.

Solutions

  1. Resolve the root id: execution.getProcessInstanceId() gives the process instance id — use that
  2. If you have an ExecutionEntity, check isProcessInstanceType() before using its id
  3. Get ids from runtimeService.createProcessInstanceQuery() instead of createExecutionQuery() when you need instances

Example fix

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

Strategy: type-guard

Validate before calling

if (executionEntity != null && !executionEntity.isProcessInstanceType()) {
    instanceId = executionEntity.getProcessInstanceId();
}

Type guard

String toProcessInstanceId(ExecutionEntity e) {
    return (e != null && e.isProcessInstanceType()) ? e.getId() : e.getProcessInstanceId();
}

Try / catch

try {
    runtimeService.setProcessDefinitionVersion(executionId, version);
} catch (ActivitiIllegalArgumentException e) {
    log.error("Need root execution id: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Passing an Execution.getId() (from runtimeService.createExecutionQuery() or a receive-task/message correlation) into setProcessDefinitionVersion instead of the ProcessInstance.getId().

Common situations: Code that holds only an ExecutionEntity (e.g. inside a delegate or event listener) and uses its id directly; message boundary events on embedded sub-processes returning child execution ids.

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 Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/07f35cde544ab5d2. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/cmd/SetProcessDefinitionVersionCmd.java:93

                "' has been provided."
            );
        }
        this.processInstanceId = processInstanceId;
        this.processDefinitionVersion = processDefinitionVersion;
    }

    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.findById(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."
            );
        }

        DeploymentManager deploymentCache = commandContext.getProcessEngineConfiguration().getDeploymentManager();
        ProcessDefinition currentProcessDefinition = deploymentCache.findDeployedProcessDefinitionById(
            processInstance.getProcessDefinitionId()
        );

View on GitHub (pinned to 56435b1a97)