flowable/flowable-engine · error · FlowableObjectNotFoundException

No historic task exists with the given id:

Error message

No historic task exists with the given id: 

What it means

This FlowableObjectNotFoundException is thrown by GetHistoricIdentityLinksForTaskCmd when the historic task service cannot find a HistoricTaskInstance matching the supplied taskId. Historic identity links (assignee, owner, candidates) only exist as attachments to a historic task record, so if the historic task is absent there is nothing to return. The library throws rather than returning null so callers can distinguish 'bad id' from 'task with no identity links'.

Source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/GetHistoricIdentityLinksForTaskCmd.java:63

        this.processInstanceId = processInstanceId;
    }

    @Override
    public List<HistoricIdentityLink> execute(CommandContext commandContext) {
        if (taskId != null) {
            return getLinksForTask(commandContext);
        } else {
            return getLinksForProcessInstance(commandContext);
        }
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected List<HistoricIdentityLink> getLinksForTask(CommandContext commandContext) {
        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
        HistoricTaskInstanceEntity task = processEngineConfiguration.getTaskServiceConfiguration().getHistoricTaskService().getHistoricTask(taskId);

        if (task == null) {
            throw new FlowableObjectNotFoundException("No historic task exists with the given id: " + taskId, HistoricTaskInstance.class);
        }

        HistoricIdentityLinkService historicIdentityLinkService = processEngineConfiguration.getIdentityLinkServiceConfiguration().getHistoricIdentityLinkService();
        List<HistoricIdentityLinkEntity> identityLinks = historicIdentityLinkService.findHistoricIdentityLinksByTaskId(taskId);

        HistoricIdentityLinkEntity assigneeIdentityLink = null;
        HistoricIdentityLinkEntity ownerIdentityLink = null;
        for (HistoricIdentityLinkEntity historicIdentityLink : identityLinks) {
            if (IdentityLinkType.ASSIGNEE.equals(historicIdentityLink.getType())) {
                assigneeIdentityLink = historicIdentityLink;

            } else if (IdentityLinkType.OWNER.equals(historicIdentityLink.getType())) {
                ownerIdentityLink = historicIdentityLink;
            }
        }

        // Similar to GetIdentityLinksForTask, return assignee and owner as identity link
        if (task.getAssignee() != null && assigneeIdentityLink == null) {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the taskId exists in history: historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult() — if null, the id is wrong or history is gone
  2. If the task is still running, fetch identity links from TaskService.getIdentityLinksForTask(taskId) instead of the history API
  3. Check the engine's historyLevel configuration; at level 'none' or 'activity' fewer/no historic task records are produced
  4. Confirm you are connected to the same database the id was issued from (datasource/JNDI config)
  5. Wrap the call in try/catch for FlowableObjectNotFoundException and handle the absent-task case gracefully

Example fix

// before
List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForTask(taskId);
// after
HistoricTaskInstance ht = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
List<HistoricIdentityLink> links = (ht != null)
    ? historyService.getHistoricIdentityLinksForTask(taskId)
    : Collections.emptyList();
Defensive patterns

Strategy: try-catch

Validate before calling

HistoricTaskInstance ht = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
if (ht == null) { /* task not in history: skip or use runtime TaskService */ }

Type guard

boolean historicTaskExists(String id) {
  return id != null && historyService.createHistoricTaskInstanceQuery().taskId(id).count() > 0;
}

Try / catch

try {
  List<HistoricIdentityLink> links = historyService.getHistoricIdentityLinksForTask(taskId);
} catch (FlowableObjectNotFoundException e) {
  logger.warn("No historic task for id {}: {}", taskId, e.getMessage());
  links = Collections.emptyList();
}

Prevention

When it happens

Trigger: Calling HistoryService.getHistoricIdentityLinksForTask(taskId) (or RuntimeService variants routed here) with a taskId that has no row in ACT_HI_TASKINST — e.g. a still-running task never yet written to history, a deleted history, or a plain typo'd/transplanted id from another database.

Common situations: Querying history right after a task was created but before the history level flushes it; running with history level 'none' so no historic tasks are persisted; pointing an app at a different DB/schema (test vs prod) than where the id came from; hard-delete cleanup jobs removing historic data while reports still reference old ids.

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