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
- Check existence first: taskService.createTaskQuery().taskId(taskId).singleResult()
- If the task was completed, query historyService.createHistoricTaskInstanceQuery().taskId(id) and use history identity-link APIs
- Re-fetch the task id from the process variables/query instead of caching stale ids in the UI
- Confirm the datasource points at the same database the task id came from
- 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
- Re-check task existence before each identity-link operation on user-facing flows
- Use historic task queries when tasks may already be completed
- Don't pass historic task ids to runtime TaskService APIs
- Log the taskId in your own wrapper since this error message omits it
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
- Cannot find process definition with id
- Cannot find process definition with id
- Cannot find task with id
- Cannot find task with id
- Cannot find task with id
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)