{"record":{"id":"60d73f3748b36ebe","repo":"flowable/flowable-engine","slug":"taskid-is-null-60d73f","errorCode":null,"errorMessage":"taskId is null","messagePattern":"taskId is null","errorType":"validation","errorClass":"ActivitiIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/DeleteHistoricTaskInstanceCmd.java","lineNumber":38,"sourceCode":"import org.activiti.engine.impl.interceptor.CommandContext;\n\n/**\n * @author Tom Baeyens\n */\npublic class DeleteHistoricTaskInstanceCmd implements Command<Object>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n    protected String taskId;\n\n    public DeleteHistoricTaskInstanceCmd(String taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public Object execute(CommandContext commandContext) {\n\n        if (taskId == null) {\n            throw new ActivitiIllegalArgumentException(\"taskId is null\");\n        }\n        commandContext\n                .getHistoricTaskInstanceEntityManager()\n                .deleteHistoricTaskInstanceById(taskId);\n        return null;\n    }\n\n}\n","sourceCodeStart":20,"sourceCodeEnd":47,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/DeleteHistoricTaskInstanceCmd.java#L20-L47","documentation":"DeleteHistoricTaskInstanceCmd validates its taskId before touching history. A null taskId is rejected immediately with ActivitiIllegalArgumentException since no meaningful lookup or deletion is possible. This is a pure argument validation, not a lookup failure.","triggerScenarios":"Calling deleteHistoricTask(null) on the history service — typically when the id came from an uninitialized variable, a missing query result, or an unbound method parameter.","commonSituations":"Bulk cleanup scripts building task ids from optional query results; refactoring where a HistoricTaskInstance object was passed instead of its id getter; asynchronous jobs where the id field was never populated.","solutions":["Ensure the caller passes a non-null taskId string before invoking deleteHistoricTask.","Add a guard in the calling code (if (taskId == null) return/skip) for optional cleanup paths.","Check where the id originates — e.g. use historicTaskInstance.getId() not the entity itself."],"exampleFix":"// before\nhistoryService.deleteHistoricTask(taskId); // taskId may be null\n// after\nif (taskId != null) {\n    historyService.deleteHistoricTask(taskId);\n}","handlingStrategy":"validation","validationCode":"if (taskId == null || taskId.isEmpty()) {\n    return; // nothing to delete\n}","typeGuard":null,"tryCatchPattern":"try {\n    historyService.deleteHistoricTask(taskId);\n} catch (ActivitiIllegalArgumentException e) {\n    log.warn(\"Skipping history deletion: {}\", e.getMessage());\n}","preventionTips":["Always obtain the id from historicTaskInstance.getId() rather than passing entities","Null-check optional ids in bulk cleanup loops","Fail fast where the id is produced, not deep inside the delete call"],"tags":["null-argument","task","history","validation"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}