flowable/flowable-engine · error · ActivitiException

The process definition id is mandatory, but

Error message

The process definition id is mandatory, but '${processDefinitionId}' has been provided.

What it means

GetDeploymentProcessDiagramLayoutCmd's constructor validates the process definition id and throws ActivitiException when it is null or an empty string. The diagram-layout lookup command cannot proceed without a concrete process definition id, so it fails fast at command construction instead of during execution. This is a guard against passing an unset/blank id into the engine's command stack.

Solutions

  1. Pass a valid, non-empty process definition id obtained from repositoryService.createProcessDefinitionQuery() or ProcessInstance.getProcessDefinitionId().
  2. Check your own code for the variable that yields null/empty before calling the API; fix the upstream lookup.
  3. Confirm you are not accidentally passing a deploymentId or processInstanceId where a processDefinitionId is required.

Example fix

// before
DiagramLayout layout = repositoryService.getProcessDiagramLayout(processDefinitionId); // throws when null/empty
// after
if (processDefinitionId == null || processDefinitionId.isEmpty()) {
    processDefinitionId = runtimeService.createProcessInstanceQuery()
        .processInstanceId(processInstanceId).singleResult().getProcessDefinitionId();
}
DiagramLayout layout = repositoryService.getProcessDiagramLayout(processDefinitionId);
Defensive patterns

Strategy: validation

Validate before calling

if (processDefinitionId == null || processDefinitionId.trim().isEmpty()) {
    throw new IllegalArgumentException("processDefinitionId must be a non-empty string");
}

Type guard

boolean isValidProcessDefinitionId(String id) { return id != null && !id.trim().isEmpty(); }

Try / catch

try {
    DiagramLayout layout = repositoryService.getProcessDiagramLayout(processDefinitionId);
} catch (ActivitiException e) {
    if (e.getMessage() != null && e.getMessage().contains("mandatory")) {
        throw new IllegalStateException("processDefinitionId was not resolved before diagram lookup", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling runtimeService/managementService APIs that build GetDeploymentProcessDiagramLayoutCmd (e.g. repositoryService.getProcessDiagramLayout(processDefinitionId)) with a null or "" processDefinitionId.

Common situations: Developers pass a variable that was never populated because a prior deployment/process-start call returned null or the wrong field was read (e.g. using deployment id or process instance id instead of process definition id); also common after refactoring where a definition-id lookup result was not null-checked.

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

Appendix: source

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

import org.activiti.engine.impl.interceptor.Command;
import org.activiti.engine.impl.interceptor.CommandContext;
import org.activiti.engine.repository.DiagramLayout;

/**
 * Provides positions and dimensions of elements in a process diagram as provided by {@link GetDeploymentProcessDiagramCmd}.
 *
 * This command requires a process model and a diagram image to be deployed.
 *
 * @author Falko Menge
 */
public class GetDeploymentProcessDiagramLayoutCmd implements Command<DiagramLayout>, Serializable {

    private static final long serialVersionUID = 1L;
    protected String processDefinitionId;

    public GetDeploymentProcessDiagramLayoutCmd(String processDefinitionId) {
        if (processDefinitionId == null || processDefinitionId.length() < 1) {
            throw new ActivitiException("The process definition id is mandatory, but '" + processDefinitionId + "' has been provided.");
        }
        this.processDefinitionId = processDefinitionId;
    }

    @Override
    public DiagramLayout execute(CommandContext commandContext) {
        InputStream processModelStream = new GetDeploymentProcessModelCmd(processDefinitionId)
                .execute(commandContext);
        InputStream processDiagramStream = new GetDeploymentProcessDiagramCmd(processDefinitionId)
                .execute(commandContext);
        return new ProcessDiagramLayoutFactory().getProcessDiagramLayout(processModelStream, processDiagramStream);
    }

}

View on GitHub (pinned to d6d39ce1c6)