flowable/flowable-engine · error · FlowableObjectNotFoundException

Cannot find task with id " + taskId

Error message

Cannot find task with id " + taskId

What it means

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.

Solutions

  1. Before acting, check the task still exists: taskService.createTaskQuery().taskId(id).singleResult(), and handle null.
  2. If the task may be completed already, treat FlowableObjectNotFoundException as an idempotent no-op for 'complete' flows.
  3. Fetch fresh task ids from taskService.createTaskQuery() instead of reusing cached ids across sessions.
  4. Confirm the client and server point at the same Flowable schema/environment.

Example fix

// before
taskService.complete(taskId);
// after
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task != null) {
    taskService.complete(taskId);
}
Defensive patterns

Strategy: validation

Validate before calling

Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) { throw new NotFoundException("Task " + taskId + " not found or already completed"); }

Type guard

boolean taskExists(String taskId) {
    return taskId != null && taskService.createTaskQuery().taskId(taskId).count() > 0;
}

Try / catch

try {
    taskService.complete(taskId);
} catch (FlowableObjectNotFoundException e) {
    log.info("Task {} already completed/removed; treating as no-op", taskId);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/NeedsActiveTaskCmd.java:53

    protected String taskId;

    public NeedsActiveTaskCmd(String taskId) {
        this.taskId = taskId;
    }

    @Override
    public T execute(CommandContext commandContext) {

        if (taskId == null) {
            throw new FlowableIllegalArgumentException("taskId is null");
        }

        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        TaskEntity task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);

        if (task == null) {
            throw new FlowableObjectNotFoundException("Cannot find task with id " + taskId, Task.class);
        }

        if (task.isDeleted()) {
            throw new FlowableException(task + " is already deleted");
        }

        if (task.isSuspended()) {
            throw new FlowableException(getSuspendedTaskExceptionPrefix() + " a suspended " + task);
        }

        return execute(commandContext, task);
    }

    /**
     * Subclasses must implement in this method their normal command logic. The provided task is ensured to be active.
     */
    protected abstract T execute(CommandContext commandContext, TaskEntity task);

View on GitHub (pinned to d6d39ce1c6)