flowable/flowable-engine · error · FlowableIllegalArgumentException

taskId and taskIds are null

Error message

taskId and taskIds are null

What it means

DeleteTaskCmd.deleteTask requires either a single taskId or a collection of taskIds; when both are null it throws FlowableIllegalArgumentException. Unlike the process-instance delete commands, an empty collection also reaches this branch and throws, because neither field is non-null.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/DeleteTaskCmd.java:55

        this.deleteReason = deleteReason;
    }

    public DeleteTaskCmd(Collection<String> taskIds, String deleteReason, boolean cascade) {
        this.taskIds = taskIds;
        this.cascade = cascade;
        this.deleteReason = deleteReason;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (taskId != null) {
            deleteTask(commandContext, taskId);
        } else if (taskIds != null) {
            for (String taskId : taskIds) {
                deleteTask(commandContext, taskId);
            }
        } else {
            throw new FlowableIllegalArgumentException("taskId and taskIds are null");
        }

        return null;
    }

    protected void deleteTask(CommandContext commandContext, String taskId) {
        TaskHelper.deleteTask(taskId, deleteReason, cascade);
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Pass a valid taskId, or a non-empty taskIds collection.
  2. Guard before the call: throw a domain-specific error when both inputs are absent.
  3. For bulk deletion from user input, validate the list is non-empty before calling deleteTasks.
  4. Confirm you are not confusing taskId with executionId or processInstanceId.

Example fix

// before
taskService.deleteTasks(taskIds, "cleanup"); // taskIds null or empty
// after
if (taskIds != null && !taskIds.isEmpty()) {
    taskService.deleteTasks(taskIds, "cleanup");
} else if (taskId != null) {
    taskService.deleteTask(taskId, "cleanup");
}
Defensive patterns

Strategy: validation

Validate before calling

if ((taskId == null) && (taskIds == null || taskIds.isEmpty())) throw new IllegalArgumentException("taskId or non-empty taskIds required");

Try / catch

try { taskService.deleteTask(taskId, reason); } catch (FlowableIllegalArgumentException e) { log.warn("No task id provided", e); }

Prevention

When it happens

Trigger: Calling taskService.deleteTask(null) / deleteTask(null, reason), deleteTasks(null), or deleteTasks(new ArrayList<>()) — an empty list also triggers this since neither argument is set.

Common situations: REST/HTTP handlers forwarding an absent id or an empty JSON array; delete loops where the id variable was never populated; generic cleanup utilities parameterized with optional id collections left empty.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/05d7cfe94c1f0e6b. Report an issue: GitHub.