{"record":{"id":"bd9aec60d5f420cd","repo":"flowable/flowable-engine","slug":"cannot-find-task-with-id-taskid-bd9aec","errorCode":null,"errorMessage":"Cannot find task with id \" + taskId","messagePattern":"Cannot find task with id \" \\+ taskId","errorType":"exception","errorClass":"FlowableObjectNotFoundException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/NeedsActiveTaskCmd.java","lineNumber":53,"sourceCode":"\n    protected String taskId;\n\n    public NeedsActiveTaskCmd(String taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public T execute(CommandContext commandContext) {\n\n        if (taskId == null) {\n            throw new FlowableIllegalArgumentException(\"taskId is null\");\n        }\n\n        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);\n        TaskEntity task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);\n\n        if (task == null) {\n            throw new FlowableObjectNotFoundException(\"Cannot find task with id \" + taskId, Task.class);\n        }\n\n        if (task.isDeleted()) {\n            throw new FlowableException(task + \" is already deleted\");\n        }\n\n        if (task.isSuspended()) {\n            throw new FlowableException(getSuspendedTaskExceptionPrefix() + \" a suspended \" + task);\n        }\n\n        return execute(commandContext, task);\n    }\n\n    /**\n     * Subclasses must implement in this method their normal command logic. The provided task is ensured to be active.\n     */\n    protected abstract T execute(CommandContext commandContext, TaskEntity task);\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/NeedsActiveTaskCmd.java#L35-L71","documentation":"NeedsActiveTaskCmd looks the task up via the TaskService and throws FlowableObjectNotFoundException when no ACT_RU_TASK row matches the given taskId. The task either never existed or has already been completed/deleted and moved to history.","triggerScenarios":"Calling TaskService.claim/complete/resolve/setAssignee with a taskId that has no active task row, or operating on a task after another thread/user completed it.","commonSituations":"Double-submission of a task form (second complete finds nothing); stale UI holding a task id after completion; task id from history (ACT_HI_TASKINST) used against the runtime service; wrong database/environment.","solutions":["Before acting, check the task still exists: taskService.createTaskQuery().taskId(id).singleResult(), and handle null.","If the task may be completed already, treat FlowableObjectNotFoundException as an idempotent no-op for 'complete' flows.","Fetch fresh task ids from taskService.createTaskQuery() instead of reusing cached ids across sessions.","Confirm the client and server point at the same Flowable schema/environment."],"exampleFix":"// before\ntaskService.complete(taskId);\n// after\nTask task = taskService.createTaskQuery().taskId(taskId).singleResult();\nif (task != null) {\n    taskService.complete(taskId);\n}","handlingStrategy":"validation","validationCode":"Task task = taskService.createTaskQuery().taskId(taskId).singleResult();\nif (task == null) { throw new NotFoundException(\"Task \" + taskId + \" not found or already completed\"); }","typeGuard":"boolean taskExists(String taskId) {\n    return taskId != null && taskService.createTaskQuery().taskId(taskId).count() > 0;\n}","tryCatchPattern":"try {\n    taskService.complete(taskId);\n} catch (FlowableObjectNotFoundException e) {\n    log.info(\"Task {} already completed/removed; treating as no-op\", taskId);\n}","preventionTips":["Design complete/claim flows to be idempotent for already-finished tasks.","Refresh task lists from TaskQuery instead of long-lived caches.","Disable duplicate form submissions (disable button + idempotency key).","Distinguish runtime vs history ids in your APIs."],"tags":["flowable","task-not-found","stale-reference"],"backgroundTag":"record-not-found","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"}