{"record":{"id":"c5c3eaab7329e037","repo":"flowable/flowable-engine","slug":"the-process-definition-version-is-mandatory-but-c5c3ea","errorCode":null,"errorMessage":"The process definition version is mandatory, but 'null' has been provided.","messagePattern":"The process definition version is mandatory, but 'null' has been provided\\.","errorType":"exception","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SetProcessDefinitionVersionCmd.java","lineNumber":64,"sourceCode":" * If the process instance is not currently waiting but actively running, then this would be a case for optimistic locking, meaning either the version update or the \"real work\" wins, i.e., this is a\n * race condition.\n * \n * @see http://forums.activiti.org/en/viewtopic.php?t=2918\n * @author Falko Menge\n */\npublic class SetProcessDefinitionVersionCmd implements Command<Void>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n\n    private final String processInstanceId;\n    private final Integer processDefinitionVersion;\n\n    public SetProcessDefinitionVersionCmd(String processInstanceId, Integer processDefinitionVersion) {\n        if (processInstanceId == null || processInstanceId.length() < 1) {\n            throw new ActivitiIllegalArgumentException(\"The process instance id is mandatory, but '\" + processInstanceId + \"' has been provided.\");\n        }\n        if (processDefinitionVersion == null) {\n            throw new ActivitiIllegalArgumentException(\"The process definition version is mandatory, but 'null' has been provided.\");\n        }\n        if (processDefinitionVersion < 1) {\n            throw new ActivitiIllegalArgumentException(\"The process definition version must be positive, but '\" + processDefinitionVersion + \"' has been provided.\");\n        }\n        this.processInstanceId = processInstanceId;\n        this.processDefinitionVersion = processDefinitionVersion;\n    }\n\n    @Override\n    public Void execute(CommandContext commandContext) {\n        // check that the new process definition is just another version of the same\n        // process definition that the process instance is using\n        ExecutionEntityManager executionManager = commandContext.getExecutionEntityManager();\n        ExecutionEntity processInstance = executionManager.findExecutionById(processInstanceId);\n        if (processInstance == null) {\n            throw new ActivitiObjectNotFoundException(\"No process instance found for id = '\" + processInstanceId + \"'.\", ProcessInstance.class);\n        } else if (!processInstance.isProcessInstanceType()) {\n            throw new ActivitiIllegalArgumentException(","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/SetProcessDefinitionVersionCmd.java#L46-L82","documentation":"SetProcessDefinitionVersionCmd is a command that migrates a running process instance to a different version of the same process definition. Flowable5 validates all constructor arguments eagerly; a null processDefinitionVersion makes the migration target meaningless, so the command throws ActivitiIllegalArgumentException before any work is done.","triggerScenarios":"Calling new SetProcessInstanceVersionCmd(processInstanceId, null) — typically when the caller read the version from a nullable variable or an API response that did not carry the version field.","commonSituations":"Scripts that fetch a process definition version from an untyped map/JSON which returned null; integrations built against older engine APIs where version was inferred; refactoring that dropped a default version constant.","solutions":["Pass an explicit positive Integer version, e.g. new SetProcessDefinitionVersionCmd(pid, 2).","Resolve the current definition first: processEngine.getRepositoryService().createProcessDefinitionQuery().processDefinitionKey(key).orderByProcessDefinitionVersion().desc().singleResult() and pass its getVersion().","Guard the value in caller code before constructing the command and fail with a clearer domain-specific message."],"exampleFix":"// before\nruntimeService.setProcessDefinitionVersion(processInstanceId, versionFromConfig); // versionFromConfig is null\n// after\nif (versionFromConfig == null) {\n    throw new IllegalArgumentException(\"No version configured for migration of \" + processInstanceId);\n}\nruntimeService.setProcessDefinitionVersion(processInstanceId, versionFromConfig);","handlingStrategy":"validation","validationCode":"if (processDefinitionVersion == null || processDefinitionVersion < 1) {\n    throw new IllegalArgumentException(\"processDefinitionVersion must be a positive integer\");\n}","typeGuard":"boolean isValidVersion(Integer v) { return v != null && v >= 1; }","tryCatchPattern":"try {\n    runtimeService.setProcessDefinitionVersion(pid, version);\n} catch (org.activiti.engine.ActivitiIllegalArgumentException e) {\n    // log and reject the migration request\n}","preventionTips":["Always resolve the version from ProcessDefinitionQuery rather than passing user/config input directly","Validate constructor inputs at the service boundary","Use Integer (nullable) deliberately and check null before engine calls"],"tags":["java","flowable","argument-validation","null"],"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"}