{"record":{"id":"ea6c73e1bb9830dd","repo":"flowable/flowable-engine","slug":"either-processdefinitionid-processdefinitionkey-o","errorCode":null,"errorMessage":"Either processDefinitionId, processDefinitionKey or message is required.","messagePattern":"Either processDefinitionId, processDefinitionKey or message is required\\.","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":400,"severity":"error","filePath":"modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ProcessInstanceCollectionResource.java","lineNumber":331,"sourceCode":"    @ApiOperation(value = \"Start a process instance\", tags = { \"Process Instances\" },\n            notes = \"Note that also a *transientVariables* property is accepted as part of this json, that follows the same structure as the *variables* property.\\n\\n\"\n            + \"Only one of *processDefinitionId*, *processDefinitionKey* or *message* can be used in the request body. \\n\\n\"\n            + \"Parameters *businessKey*, *variables* and *tenantId* are optional.\\n\\n\"\n            + \"If tenantId is omitted, the default tenant will be used.\\n\\n \"\n            + \"It is possible to send variables, transientVariables and startFormVariables in one request.\\n\\n\"\n            + \"More information about the variable format can be found in the REST variables section.\\n\\n \"\n            + \"Note that the variable-scope that is supplied is ignored, process-variables are always local.\\n\\n\",\n            code = 201)\n    @ApiResponses(value = {\n            @ApiResponse(code = 201, message = \"Indicates the process instance was created.\"),\n            @ApiResponse(code = 400, message = \"Indicates either the process-definition was not found (based on id or key), no process is started by sending the given message or an invalid variable has been passed. Status description contains additional information about the error.\")\n    })\n    @PostMapping(value = \"/runtime/process-instances\", produces = \"application/json\")\n    @ResponseStatus(HttpStatus.CREATED)\n    public ProcessInstanceResponse createProcessInstance(@RequestBody ProcessInstanceCreateRequest request) {\n\n        if (request.getProcessDefinitionId() == null && request.getProcessDefinitionKey() == null && request.getMessage() == null) {\n            throw new FlowableIllegalArgumentException(\"Either processDefinitionId, processDefinitionKey or message is required.\");\n        }\n\n        int paramsSet = ((request.getProcessDefinitionId() != null) ? 1 : 0) + ((request.getProcessDefinitionKey() != null) ? 1 : 0) + ((request.getMessage() != null) ? 1 : 0);\n\n        if (paramsSet > 1) {\n            throw new FlowableIllegalArgumentException(\"Only one of processDefinitionId, processDefinitionKey or message should be set.\");\n        }\n\n        if (request.isTenantSet()) {\n            // Tenant-id can only be used with either key or message\n            if (request.getProcessDefinitionId() != null) {\n                throw new FlowableIllegalArgumentException(\"TenantId can only be used with either processDefinitionKey or message.\");\n            }\n        }\n        \n        Map<String, Object> startVariables = null;\n        Map<String, Object> transientVariables = null;\n        Map<String, Object> startFormVariables = null;","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ProcessInstanceCollectionResource.java#L313-L349","documentation":"FlowableIllegalArgumentException thrown by createProcessInstance (POST /runtime/process-instances) when none of processDefinitionId, processDefinitionKey, or message is set on the request body. Flowable needs at least one of these three ways to locate what to start; an empty start request is rejected before the engine is invoked. Exactly one of the three must be provided.","triggerScenarios":"POST /runtime/process-instances with a JSON body that omits all three fields or has them all as null/empty strings.","commonSituations":"Building the request programmatically with a variable map but forgetting the definition reference, deserialization dropping unknown/mismatched field names (e.g. process_definition_id in the payload), test fixtures with empty request objects.","solutions":["Add one of processDefinitionId, processDefinitionKey, or message to the request body","Prefer processDefinitionKey with the latest deployed definition version if you don't have an id","Use message when the process has a message start event","Check JSON field naming/casing matches ProcessInstanceCreateRequest (camelCase)","Confirm the client serializer is not nulling out fields you set"],"exampleFix":"// before\nPOST /runtime/process-instances\n{\"variables\":{\"a\":1}}\n// after\nPOST /runtime/process-instances\n{\"processDefinitionKey\":\"orderProcess\",\"variables\":{\"a\":1}}","handlingStrategy":"validation","validationCode":"const starters = ['processDefinitionId','processDefinitionKey','message'].filter(k => req[k] != null && req[k] !== '');\nif (starters.length === 0) throw new Error('Provide exactly one of processDefinitionId, processDefinitionKey, or message');","typeGuard":"function hasStartRef(req) {\n  return ['processDefinitionId','processDefinitionKey','message'].some(k => typeof req?.[k] === 'string' && req[k].length > 0);\n}","tryCatchPattern":"try { await startProcessInstance(req); } catch (e) { if (e.status === 400 && /Either processDefinitionId/.test(e.message)) { console.error('Add a start reference to the request'); } throw e; }","preventionTips":["Always set processDefinitionKey as the default in start-request builders","Validate the request object before serialization","Check field name casing survives serialization (camelCase)"],"tags":["rest","validation","missing-field","flowable"],"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-14T11:17:12.474Z"}