flowable/flowable-engine · error · ActivitiIllegalArgumentException
The task definition key is mandatory, but '' has been…
Error message
The task definition key is mandatory, but '' has been provided.
What it means
The GetFormKeyCmd constructor validates its arguments at construction time: taskDefinitionKey must be a non-null, non-empty string, otherwise ActivitiIllegalArgumentException is thrown immediately (before the command is ever executed). The form key is looked up per task definition, so an empty key has no meaning.
Solutions
- Pass the actual task definition key (task.getTaskDefinitionKey()); for start forms pass null/omit the taskDefinitionKey argument of the service method rather than an empty string.
- Trim and validate the key before constructing the command; strip placeholder syntax like ${...} that may resolve empty.
- Check the BPMN model: the userTask element must have a flowable:formKey or an id you intend to use as the definition key.
Example fix
// before
String key = task.getTaskDefinitionKey();
String formKey = formService.getFormKey(processDefinitionId, key); // key may be ""
// after
String key = task.getTaskDefinitionKey();
if (key == null || key.trim().isEmpty()) {
throw new IllegalArgumentException("task definition key is required to resolve the form key");
}
String formKey = formService.getFormKey(processDefinitionId, key.trim()); Defensive patterns
Strategy: validation
Validate before calling
if (taskDefinitionKey == null || taskDefinitionKey.trim().isEmpty()) {
throw new IllegalArgumentException("A non-empty task definition key is required to fetch the form key");
} Type guard
boolean hasTaskDefinitionKey(String key) { return key != null && !key.trim().isEmpty(); } Try / catch
try {
return formService.getFormKey(processDefinitionId, taskDefinitionKey);
} catch (ActivitiIllegalArgumentException e) {
if (e.getMessage().contains("task definition key is mandatory")) { log.warn("Empty task definition key"); return null; }
throw e;
} Prevention
- Use task.getTaskDefinitionKey() rather than hand-built strings.
- For start forms, use the getFormKey(processDefinitionId) overload instead of passing an empty key.
- Check BPMN userTask definitions for a real id/formKey before querying.
When it happens
Trigger: new GetFormKeyCmd(processDefinitionId, "") or (processDefinitionId, null); calling FormService.getFormKey(processDefinitionId, taskDefinitionKey) where the task definition key argument is empty, e.g. taken from a StartFormData/task object that lacks a key.
Common situations: Retrieving the form key for a start event using the wrong overload or an empty task definition key, template/property placeholders that resolved to empty strings, or data from a task whose definition key was never set.
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
- A dynamically created plan item can only be injected into a…
- batchSize has to be larger than 0
- Cannot set both body and form parameters
- Cannot set both body bytes and form parameters
- Child form variables can only be set when starting a plan…
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/7ac1647a080cd37c.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/GetFormKeyCmd.java:46
public class GetFormKeyCmd implements Command<String> {
protected String taskDefinitionKey;
protected String processDefinitionId;
/**
* Retrieves a start form key.
*/
public GetFormKeyCmd(String processDefinitionId) {
setProcessDefinitionId(processDefinitionId);
}
/**
* Retrieves a task form key.
*/
public GetFormKeyCmd(String processDefinitionId, String taskDefinitionKey) {
setProcessDefinitionId(processDefinitionId);
if (taskDefinitionKey == null || taskDefinitionKey.length() < 1) {
throw new ActivitiIllegalArgumentException("The task definition key is mandatory, but '" + taskDefinitionKey + "' has been provided.");
}
this.taskDefinitionKey = taskDefinitionKey;
}
protected void setProcessDefinitionId(String processDefinitionId) {
if (processDefinitionId == null || processDefinitionId.length() < 1) {
throw new ActivitiIllegalArgumentException("The process definition id is mandatory, but '" + processDefinitionId + "' has been provided.");
}
this.processDefinitionId = processDefinitionId;
}
@Override
public String execute(CommandContext commandContext) {
ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) commandContext
.getProcessEngineConfiguration()
.getDeploymentManager()
.findDeployedProcessDefinitionById(processDefinitionId);
DefaultFormHandler formHandler;View on GitHub (pinned to d6d39ce1c6)