flowable/flowable-engine · error · FlowableObjectNotFoundException

task not found

Error message

task not found

What it means

GetIdentityLinksForTaskCmd.execute loads the TaskEntity via TaskService.getTask(taskId) and throws FlowableObjectNotFoundException with the terse message 'task not found' when it is null. Identity links (candidate users/groups) live on the task, so a nonexistent task cannot be queried. Note the message does not include the taskId, which makes diagnosing harder.

Solutions

  1. Check existence first: taskService.createTaskQuery().taskId(taskId).singleResult()
  2. If the task was completed, query historyService.createHistoricTaskInstanceQuery().taskId(id) and use history identity-link APIs
  3. Re-fetch the task id from the process variables/query instead of caching stale ids in the UI
  4. Confirm the datasource points at the same database the task id came from
  5. Catch FlowableObjectNotFoundException around the call and show a 'task no longer available' message

Example fix

// before
List<IdentityLink> links = taskService.getIdentityLinksForTask(taskId);
// after
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
List<IdentityLink> links = (task != null)
    ? taskService.getIdentityLinksForTask(taskId)
    : Collections.emptyList();
Defensive patterns

Strategy: try-catch

Validate before calling

Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task == null) { /* completed/absent: fall back to history API */ }

Try / catch

try {
  List<IdentityLink> links = taskService.getIdentityLinksForTask(taskId);
} catch (FlowableObjectNotFoundException e) {
  logger.warn("Task {} no longer exists (may be completed)", taskId);
  links = Collections.emptyList();
}

Prevention

When it happens

Trigger: Calling TaskService.getIdentityLinksForTask(taskId) with a taskId not present in ACT_RU_TASK — task already completed/deleted, id typo, or id from another database/history-only record.

Common situations: User clicks a stale link to a task completed moments earlier; job processed the task between fetch and this call; passing a historic task id to the runtime TaskService; cluster setups where a different DB is hit than expected.

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/cde0e832a993397d. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/GetIdentityLinksForTaskCmd.java:48

 * @author Falko Menge
 */
public class GetIdentityLinksForTaskCmd implements Command<List<IdentityLink>>, Serializable {

    private static final long serialVersionUID = 1L;
    protected String taskId;

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

    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public List<IdentityLink> execute(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        TaskEntity task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);
        
        if (task == null) {
            throw new FlowableObjectNotFoundException("task not found");
        }

        List<IdentityLink> identityLinks = (List) task.getIdentityLinks();

        // assignee is not part of identity links in the db.
        // so if there is one, we add it here.
        // @Tom: we discussed this long on skype and you agreed ;-)
        // an assignee *is* an identityLink, and so must it be reflected in the API
        //
        // Note: we cant move this code to the TaskEntity (which would be cleaner),
        // since the task.delete cascaded to all associated identityLinks
        // and of course this leads to exception while trying to delete a non-existing identityLink
        if (task.getAssignee() != null) {
            IdentityLinkEntity identityLink = processEngineConfiguration.getIdentityLinkServiceConfiguration().getIdentityLinkService().createIdentityLink();
            identityLink.setUserId(task.getAssignee());
            identityLink.setType(IdentityLinkType.ASSIGNEE);
            identityLink.setTaskId(task.getId());
            identityLinks.add(identityLink);

View on GitHub (pinned to d6d39ce1c6)