flowable/flowable-engine · error · FlowableIllegalArgumentException

processDefinitionId is required

Error message

processDefinitionId is required

What it means

Flowable REST throws FlowableIllegalArgumentException when injecting a dynamic 'subprocess' into a running process instance without providing processDefinitionId in the request body. The embedded subprocess needs a reference to a deployed dynamic subprocess definition.

Solutions

  1. Add processDefinitionId to the inject-activity request body.
  2. First deploy the dynamic subprocess definition via DynamicBpmnService / repository API and use its returned definition id.
  3. Confirm injectionType really should be 'subprocess' and not 'usertask'.

Example fix

// before
{"injectionType":"subprocess","id":"mySubProcess"}
// after
{"injectionType":"subprocess","id":"mySubProcess","processDefinitionId":"myProcess:1:104","taskId":"userTask1"}
Defensive patterns

Strategy: validation

Validate before calling

if (injectionType === 'subprocess' && !body.processDefinitionId) throw new Error('processDefinitionId required for subprocess injection');

Prevention

When it happens

Trigger: POST /runtime/process-instances/{id}/inject-activity with {"injectionType":"subprocess","id":"..."} but no processDefinitionId field.

Common situations: Developer reuses the JSON body used for injectionType 'usertask' (which doesn't need processDefinitionId); forgot to deploy the subprocess definition first and so had no id to reference.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ProcessInstanceResource.java:303

        if (restApiInterceptor != null) {
            restApiInterceptor.injectActivity(processInstance, injectActivityRequest);
        }

        if ("task".equalsIgnoreCase(injectActivityRequest.getInjectionType())) {
            DynamicUserTaskBuilder taskBuilder = new DynamicUserTaskBuilder();
            taskBuilder.id(injectActivityRequest.getId())
                .name(injectActivityRequest.getName())
                .assignee(injectActivityRequest.getAssignee());
            
            if (injectActivityRequest.getTaskId() != null) {
                dynamicBpmnService.injectParallelUserTask(injectActivityRequest.getTaskId(), taskBuilder);
            } else {
                dynamicBpmnService.injectUserTaskInProcessInstance(processInstanceId, taskBuilder);
            }
        
        } else if ("subprocess".equalsIgnoreCase(injectActivityRequest.getInjectionType())) {
            if (StringUtils.isEmpty(injectActivityRequest.getProcessDefinitionId())) {
                throw new FlowableIllegalArgumentException("processDefinitionId is required");
            }
            DynamicEmbeddedSubProcessBuilder subProcessBuilder = new DynamicEmbeddedSubProcessBuilder();
            subProcessBuilder.id(injectActivityRequest.getId())
                .processDefinitionId(injectActivityRequest.getProcessDefinitionId());
            
            if (injectActivityRequest.getTaskId() != null) {
                dynamicBpmnService.injectParallelEmbeddedSubProcess(injectActivityRequest.getTaskId(), subProcessBuilder);
            } else {
                dynamicBpmnService.injectEmbeddedSubProcessInProcessInstance(processInstanceId, subProcessBuilder);
            }
        
        } else {
            throw new FlowableIllegalArgumentException("injection type is not supported " + injectActivityRequest.getInjectionType());
        }
    }

    protected ProcessInstanceResponse activateProcessInstance(ProcessInstance processInstance) {
        if (!processInstance.isSuspended()) {

View on GitHub (pinned to d6d39ce1c6)