flowable/flowable-engine · error · FlowableIllegalArgumentException
Only one of processDefinitionId, processDefinitionKey or…
Error message
Only one of processDefinitionId, processDefinitionKey or message should be set.
What it means
FlowableIllegalArgumentException thrown by createProcessInstance when more than one of processDefinitionId, processDefinitionKey, or message is set in the request. The three fields are mutually exclusive: each names a different start mechanism (by id, by key, or by message start event), so Flowable refuses to guess. Exactly one must be supplied.
Solutions
- Remove all but one of processDefinitionId, processDefinitionKey, and message from the request
- Prefer processDefinitionId when you have it; otherwise keep processDefinitionKey and drop message
- Null out unused fields explicitly before sending
- Sanitize/whitelist fields when mapping internal objects into the REST request
Example fix
// before
{"processDefinitionKey":"orderProcess","message":"orderReceived"}
// after
{"processDefinitionKey":"orderProcess"} Defensive patterns
Strategy: validation
Validate before calling
const set = ['processDefinitionId','processDefinitionKey','message'].filter(k => req[k] != null);
if (set.length > 1) throw new Error(`Only one start reference allowed, got: ${set.join(',')}`); Type guard
function hasExactlyOneStartRef(req) {
const n = ['processDefinitionId','processDefinitionKey','message'].filter(k => req?.[k] != null).length;
return n === 1;
} Try / catch
try { await startProcessInstance(req); } catch (e) { if (e.status === 400 && /Only one of/.test(e.message)) { stripExtraStartRefs(req); } throw e; } Prevention
- Explicitly null unused start-reference fields before sending
- Whitelist fields when mapping internal objects into the REST request
- Prefer processDefinitionId over key/message when an id is known
When it happens
Trigger: POST /runtime/process-instances with two or all three of processDefinitionId/processDefinitionKey/message non-null in the body, e.g. copying a full config object into the request.
Common situations: Serializing an object that carries both key and message from application state, clients adding message for signal/event support while a key is already present, templates pre-filled with defaults not cleared.
Related errors
- A group or a user is required to create an identity link.
- A group or a user is required to create an identity link.
- Cannot combine onlyBpmn() with onlyCmmn() in the same query
- Cannot combine onlyCmmn() with onlyBpmn() in the same query
- Cannot combine scopeType(String) with onlyBpmn() in the…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/460696e4e4e193c9.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/runtime/process/ProcessInstanceCollectionResource.java:337
+ "More information about the variable format can be found in the REST variables section.\n\n "
+ "Note that the variable-scope that is supplied is ignored, process-variables are always local.\n\n",
code = 201)
@ApiResponses(value = {
@ApiResponse(code = 201, message = "Indicates the process instance was created."),
@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.")
})
@PostMapping(value = "/runtime/process-instances", produces = "application/json")
@ResponseStatus(HttpStatus.CREATED)
public ProcessInstanceResponse createProcessInstance(@RequestBody ProcessInstanceCreateRequest request) {
if (request.getProcessDefinitionId() == null && request.getProcessDefinitionKey() == null && request.getMessage() == null) {
throw new FlowableIllegalArgumentException("Either processDefinitionId, processDefinitionKey or message is required.");
}
int paramsSet = ((request.getProcessDefinitionId() != null) ? 1 : 0) + ((request.getProcessDefinitionKey() != null) ? 1 : 0) + ((request.getMessage() != null) ? 1 : 0);
if (paramsSet > 1) {
throw new FlowableIllegalArgumentException("Only one of processDefinitionId, processDefinitionKey or message should be set.");
}
if (request.isTenantSet()) {
// Tenant-id can only be used with either key or message
if (request.getProcessDefinitionId() != null) {
throw new FlowableIllegalArgumentException("TenantId can only be used with either processDefinitionKey or message.");
}
}
Map<String, Object> startVariables = null;
Map<String, Object> transientVariables = null;
Map<String, Object> startFormVariables = null;
if (request.getStartFormVariables() != null && !request.getStartFormVariables().isEmpty()) {
startFormVariables = new HashMap<>();
for (RestVariable variable : request.getStartFormVariables()) {
if (variable.getName() == null) {
throw new FlowableIllegalArgumentException("Variable name is required.");
}View on GitHub (pinned to d6d39ce1c6)