{"record":{"id":"3197bc8ddaa8b991","repo":"Activiti/Activiti","slug":"an-originaltask-is-needed-before-setting-an-update","errorCode":null,"errorMessage":"an originalTask is needed before setting an updatedTask","messagePattern":"an originalTask is needed before setting an updatedTask","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/task/TaskComparatorImpl.java","lineNumber":36,"sourceCode":"import java.util.Date;\nimport java.util.Objects;\nimport java.util.function.Function;\nimport org.activiti.engine.impl.persistence.entity.TaskEntityImpl;\nimport org.activiti.engine.task.TaskInfo;\nimport org.apache.commons.lang3.StringUtils;\n\npublic class TaskComparatorImpl implements TaskComparator {\n\n    private TaskInfo originalTask;\n    private TaskInfo updatedTask;\n\n    public void setOriginalTask(TaskInfo task) {\n        this.originalTask = copyInformationFromTaskInfo(task);\n    }\n\n    public void setUpdatedTask(TaskInfo task) {\n        if (originalTask == null) {\n            throw new IllegalArgumentException(\"an originalTask is needed before setting an updatedTask\");\n        }\n        this.updatedTask = copyInformationFromTaskInfo(task);\n    }\n\n    public TaskInfo getOriginalTask() {\n        return originalTask;\n    }\n\n    public TaskInfo getUpdatedTask() {\n        return updatedTask;\n    }\n\n    public boolean hasTaskNameChanged() {\n        return hasStringFieldChanged(TaskInfo::getName);\n    }\n\n    public boolean hasTaskDefinitionKeyChanged() {\n        return hasStringFieldChanged(TaskInfo::getTaskDefinitionKey);","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/Activiti/Activiti/blob/56435b1a97deeafdc09dd40074b056c89fba5a8a/activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/bpmn/helper/task/TaskComparatorImpl.java#L18-L54","documentation":"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.","triggerScenarios":"Calling setUpdatedTask(task) on a fresh TaskComparatorImpl before setOriginalTask(original) has been invoked; resetting the comparator without re-setting the original task.","commonSituations":"Misusing the task-listener change-detection API by only providing the updated task; constructing the comparator in tests and calling setters out of order.","solutions":["Call setOriginalTask(originalTask) before setUpdatedTask(updatedTask)","Refactor to a constructor or single method taking both tasks to enforce ordering","In tests, always set the original task in setup before the updated one"],"exampleFix":"// before\ncomparator.setUpdatedTask(updatedTask);\n// after\ncomparator.setOriginalTask(originalTask);\ncomparator.setUpdatedTask(updatedTask);","handlingStrategy":"validation","validationCode":"// enforce ordering at the call site\nif (comparator.getOriginalTask() == null) {\n    comparator.setOriginalTask(originalTask);\n}\ncomparator.setUpdatedTask(updatedTask);","typeGuard":null,"tryCatchPattern":"try {\n    comparator.setUpdatedTask(updatedTask);\n} catch (IllegalArgumentException e) {\n    log.error(\"original task snapshot missing; set it first\", e);\n}","preventionTips":["Always pair setOriginalTask with setUpdatedTask in that order","Wrap the two calls in one helper method","Initialize the original task in test setup (@Before)","Consider a constructor taking both tasks"],"tags":["task","api-misuse","ordering"],"backgroundTag":"invalid-state-transition","analyzedSha":"56435b1a97deeafdc09dd40074b056c89fba5a8a","analyzedAt":"2026-09-09T21:00:06.703Z","contentChangedAt":"2026-09-09T21:00:06.703Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}