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
- Verify the taskId exists in history: historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult() — if null, the id is wrong or history is gone
- If the task is still running, fetch identity links from TaskService.getIdentityLinksForTask(taskId) instead of the history API
- Check the engine's historyLevel configuration; at level 'none' or 'activity' fewer/no historic task records are produced
- Confirm you are connected to the same database the id was issued from (datasource/JNDI config)
- 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
- Check the historic task exists before querying its identity links
- For active tasks use TaskService identity-link APIs, not the history API
- Verify history level configuration produces historic task records
- Ensure all environments point at the same database as the id source
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
- No historic task exists with the given id:
- No case instance found for id
- Could not find a case instance with id '${caseInstanceId}'.
- Could not find a milestone instance with id '${milestoneInst
- Could not find a plan item instance with id '${planItemInsta
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/fc0e66e98d43296a.
Report an issue: GitHub.