{"record":{"id":"8e68ee0b381c7e50","repo":"flowable/flowable-engine","slug":"the-process-definition-id-is-mandatory-but-pro-8e68ee","errorCode":null,"errorMessage":"The process definition id is mandatory, but '${processDefinitionId}' has been provided.","messagePattern":"The process definition id is mandatory, but '(.+?)' has been provided\\.","errorType":"exception","errorClass":"ActivitiException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/GetDeploymentProcessDiagramLayoutCmd.java","lineNumber":39,"sourceCode":"import org.activiti.engine.impl.interceptor.Command;\nimport org.activiti.engine.impl.interceptor.CommandContext;\nimport org.activiti.engine.repository.DiagramLayout;\n\n/**\n * Provides positions and dimensions of elements in a process diagram as provided by {@link GetDeploymentProcessDiagramCmd}.\n *\n * This command requires a process model and a diagram image to be deployed.\n *\n * @author Falko Menge\n */\npublic class GetDeploymentProcessDiagramLayoutCmd implements Command<DiagramLayout>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n    protected String processDefinitionId;\n\n    public GetDeploymentProcessDiagramLayoutCmd(String processDefinitionId) {\n        if (processDefinitionId == null || processDefinitionId.length() < 1) {\n            throw new ActivitiException(\"The process definition id is mandatory, but '\" + processDefinitionId + \"' has been provided.\");\n        }\n        this.processDefinitionId = processDefinitionId;\n    }\n\n    @Override\n    public DiagramLayout execute(CommandContext commandContext) {\n        InputStream processModelStream = new GetDeploymentProcessModelCmd(processDefinitionId)\n                .execute(commandContext);\n        InputStream processDiagramStream = new GetDeploymentProcessDiagramCmd(processDefinitionId)\n                .execute(commandContext);\n        return new ProcessDiagramLayoutFactory().getProcessDiagramLayout(processModelStream, processDiagramStream);\n    }\n\n}\n","sourceCodeStart":21,"sourceCodeEnd":54,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/GetDeploymentProcessDiagramLayoutCmd.java#L21-L54","documentation":"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.","triggerScenarios":"Calling runtimeService/managementService APIs that build GetDeploymentProcessDiagramLayoutCmd (e.g. repositoryService.getProcessDiagramLayout(processDefinitionId)) with a null or \"\" processDefinitionId.","commonSituations":"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.","solutions":["Pass a valid, non-empty process definition id obtained from repositoryService.createProcessDefinitionQuery() or ProcessInstance.getProcessDefinitionId().","Check your own code for the variable that yields null/empty before calling the API; fix the upstream lookup.","Confirm you are not accidentally passing a deploymentId or processInstanceId where a processDefinitionId is required."],"exampleFix":"// before\nDiagramLayout layout = repositoryService.getProcessDiagramLayout(processDefinitionId); // throws when null/empty\n// after\nif (processDefinitionId == null || processDefinitionId.isEmpty()) {\n    processDefinitionId = runtimeService.createProcessInstanceQuery()\n        .processInstanceId(processInstanceId).singleResult().getProcessDefinitionId();\n}\nDiagramLayout layout = repositoryService.getProcessDiagramLayout(processDefinitionId);","handlingStrategy":"validation","validationCode":"if (processDefinitionId == null || processDefinitionId.trim().isEmpty()) {\n    throw new IllegalArgumentException(\"processDefinitionId must be a non-empty string\");\n}","typeGuard":"boolean isValidProcessDefinitionId(String id) { return id != null && !id.trim().isEmpty(); }","tryCatchPattern":"try {\n    DiagramLayout layout = repositoryService.getProcessDiagramLayout(processDefinitionId);\n} catch (ActivitiException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"mandatory\")) {\n        throw new IllegalStateException(\"processDefinitionId was not resolved before diagram lookup\", e);\n    }\n    throw e;\n}","preventionTips":["Always source the id from a ProcessDefinition/ProcessInstance object, never from hand-built strings.","Validate ids at service-layer boundaries before touching the engine API."],"tags":["process-definition","null-argument","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}