Activiti/Activiti · error · IllegalArgumentException

an originalTask is needed before setting an updatedTask

Error message

an originalTask is needed before setting an updatedTask

What it means

TaskComparatorImpl.setUpdatedTask throws IllegalArgumentException if setOriginalTask has not been called first, since change detection requires an original snapshot to diff against. The comparator enforces original-then-updated ordering.

Solutions

  1. Call setOriginalTask(originalTask) before setUpdatedTask(updatedTask)
  2. Refactor to a constructor or single method taking both tasks to enforce ordering
  3. In tests, always set the original task in setup before the updated one

Example fix

// before
comparator.setUpdatedTask(updatedTask);
// after
comparator.setOriginalTask(originalTask);
comparator.setUpdatedTask(updatedTask);
Defensive patterns

Strategy: validation

Validate before calling

// enforce ordering at the call site
if (comparator.getOriginalTask() == null) {
    comparator.setOriginalTask(originalTask);
}
comparator.setUpdatedTask(updatedTask);

Try / catch

try {
    comparator.setUpdatedTask(updatedTask);
} catch (IllegalArgumentException e) {
    log.error("original task snapshot missing; set it first", e);
}

Prevention

When it happens

Trigger: Calling setUpdatedTask(task) on a fresh TaskComparatorImpl before setOriginalTask(original) has been invoked; resetting the comparator without re-setting the original task.

Common situations: Misusing the task-listener change-detection API by only providing the updated task; constructing the comparator in tests and calling setters out of order.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09). Data as JSON: /api/errors/3197bc8ddaa8b991. Report an issue: GitHub.

Appendix: source

Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/task/TaskComparatorImpl.java:36

import java.util.Date;
import java.util.Objects;
import java.util.function.Function;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.activiti.engine.task.TaskInfo;
import org.apache.commons.lang3.StringUtils;

public class TaskComparatorImpl implements TaskComparator {

    private TaskInfo originalTask;
    private TaskInfo updatedTask;

    public void setOriginalTask(TaskInfo task) {
        this.originalTask = copyInformationFromTaskInfo(task);
    }

    public void setUpdatedTask(TaskInfo task) {
        if (originalTask == null) {
            throw new IllegalArgumentException("an originalTask is needed before setting an updatedTask");
        }
        this.updatedTask = copyInformationFromTaskInfo(task);
    }

    public TaskInfo getOriginalTask() {
        return originalTask;
    }

    public TaskInfo getUpdatedTask() {
        return updatedTask;
    }

    public boolean hasTaskNameChanged() {
        return hasStringFieldChanged(TaskInfo::getName);
    }

    public boolean hasTaskDefinitionKeyChanged() {
        return hasStringFieldChanged(TaskInfo::getTaskDefinitionKey);

View on GitHub (pinned to 56435b1a97)