flowable/flowable-engine · error · FlowableObjectNotFoundException
task " + taskId + " doesn't exist
Error message
task " + taskId + " doesn't exist
What it means
HasTaskVariableCmd.execute() looks up the task by id via the task service; when no TaskEntity exists for the given taskId it throws FlowableObjectNotFoundException ('task <id> doesn't exist'). This means the id is well-formed but references a task that is not in the database.
Solutions
- Verify the task exists first with taskService.createTaskQuery().taskId(id).count() > 0, or use hasVariable on a re-fetched TaskInfo.
- Re-check where the taskId is sourced from; refresh it from a fresh task query if it is stale.
- Confirm the engine points at the correct database and tenant for this task id.
- Catch FlowableObjectNotFoundException and return false / re-query instead of failing the request.
Example fix
// before
boolean has = taskService.hasVariable(taskId, "approved");
// after
if (taskService.createTaskQuery().taskId(taskId).count() == 0) {
throw new IllegalStateException("Task no longer exists: " + taskId);
}
boolean has = taskService.hasVariable(taskId, "approved"); Defensive patterns
Strategy: try-catch
Validate before calling
boolean taskExists = taskService.createTaskQuery().taskId(taskId).count() > 0;
if (!taskExists) {
throw new IllegalStateException("Task not found: " + taskId);
} Type guard
boolean taskExists(String taskId) {
return taskId != null && taskService.createTaskQuery().taskId(taskId).count() > 0;
} Try / catch
try {
return taskService.hasVariable(taskId, variableName);
} catch (FlowableObjectNotFoundException e) {
log.warn("Task {} no longer exists; treating as no-variable", taskId);
return false;
} Prevention
- Re-fetch tasks rather than caching task ids across transactions
- Account for history cleanup deleting completed tasks
- In multi-tenant setups, verify tenant before using foreign task ids
When it happens
Trigger: Calling taskService.hasVariable/hasVariableLocal with a taskId that was deleted, belongs to another database/schema, or was never created (e.g. the task was completed and removed earlier).
Common situations: Stale task ids held in UI state or cached forms after task completion; environment mismatch (test DB vs prod DB); multi-tenant setups where the id comes from a different tenant's data; history cleanup removing tasks before dependent logic runs.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Cannot find task with id " + taskId
- Cannot find task with id " + taskId
- Could not find a task instance with id
- Could not find task entity for id
- task
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/b36626169ece92ff.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/HasTaskVariableCmd.java:56
this.taskId = taskId;
this.variableName = variableName;
this.isLocal = isLocal;
}
@Override
public Boolean execute(CommandContext commandContext) {
if (taskId == null) {
throw new FlowableIllegalArgumentException("taskId is null");
}
if (variableName == null) {
throw new FlowableIllegalArgumentException("variableName is null");
}
ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext);
TaskEntity task = processEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);
if (task == null) {
throw new FlowableObjectNotFoundException("task " + taskId + " doesn't exist", Task.class);
}
boolean hasVariable = false;
if (isLocal) {
hasVariable = task.hasVariableLocal(variableName);
} else {
hasVariable = task.hasVariable(variableName);
}
return hasVariable;
}
}
View on GitHub (pinned to d6d39ce1c6)