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

  1. 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.
  2. Trim and validate the key before constructing the command; strip placeholder syntax like ${...} that may resolve empty.
  3. 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

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


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)