flowable/flowable-engine · error · FlowableIllegalArgumentException

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 ${class simple name} with a root execution id.

What it means

Thrown by execute() when the given id resolves to an execution, but that execution is a child execution rather than the root process-instance execution. Business key is stored on the root execution, so Flowable refuses to set it on a child and points you at the correct root id.

Solutions

  1. Use processInstance.getId() / execution.getProcessInstanceId() (root id) instead of the child execution id.
  2. If you only have an Execution, call execution.getProcessInstanceId() to get the root and pass that.
  3. Query RuntimeService.createProcessInstanceQuery().processInstanceId(...) to confirm the id is of process instance type.

Example fix

// before
runtimeService.setProcessInstanceBusinessKey(task.getExecutionId(), key);
// after
runtimeService.setProcessInstanceBusinessKey(task.getProcessInstanceId(), key);
Defensive patterns

Strategy: type-guard

Validate before calling

ProcessInstance pi = runtimeService.createProcessInstanceQuery()
        .processInstanceId(candidateId).singleResult();
boolean isRoot = pi != null && candidateId.equals(pi.getId());

Type guard

boolean isProcessInstanceRoot(String id, RuntimeService rs) {
    ProcessInstance pi = rs.createProcessInstanceQuery().processInstanceId(id).singleResult();
    return pi != null && pi.getProcessInstanceId() == null || (pi != null && id.equals(pi.getId()));
}

Try / catch

try {
    runtimeService.setProcessInstanceBusinessKey(id, key);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().contains("points to a child execution")) {
        // switch to execution.getProcessInstanceId() and retry
    }
}

Prevention

When it happens

Trigger: Calling RuntimeService.setProcessInstanceBusinessKey with an execution id obtained from a task's getExecutionId() (which is usually a child/scope execution), not from ProcessInstance.getId().

Common situations: Developers inside a delegate/task listener use DelegateExecution.getId() or Task.getExecutionId() and pass that as a process instance id; scope executions (embedded sub-processes, call activities) frequently differ from the root id.

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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/SetProcessInstanceBusinessKeyCmd.java:66

        this.processInstanceId = processInstanceId;
        this.businessKey = businessKey;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        ExecutionEntityManager executionManager = CommandContextUtil.getExecutionEntityManager(commandContext);
        ExecutionEntity processInstance = executionManager.findById(processInstanceId);
        if (processInstance == null) {
            if (CommandContextUtil.getProcessEngineConfiguration(commandContext).isFlowable5CompatibilityEnabled()) {
                CommandContextUtil.getProcessEngineConfiguration(commandContext).getFlowable5CompatibilityHandler().updateBusinessKey(processInstanceId,
                        businessKey);
                return null;
            }
            
            throw new FlowableObjectNotFoundException("No process instance found for id = '" + processInstanceId + "'.", ProcessInstance.class);
        } else if (!processInstance.isProcessInstanceType()) {
            throw new FlowableIllegalArgumentException("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.");
        }

        if (Flowable5Util.isFlowable5ProcessDefinitionId(commandContext, processInstance.getProcessDefinitionId())) {
            CommandContextUtil.getProcessEngineConfiguration(commandContext).getFlowable5CompatibilityHandler().updateBusinessKey(processInstanceId, businessKey);
            return null;
        }

        executionManager.updateProcessInstanceBusinessKey(processInstance, businessKey);

        return null;
    }
}

View on GitHub (pinned to d6d39ce1c6)