flowable/flowable-engine · error · FlowableObjectNotFoundException
Historic task instance '' couldn't be found.
Error message
Historic task instance '' couldn't be found.
What it means
FlowableObjectNotFoundException thrown when the historic task instance query by taskId plus optional scope filter returns no result. The variable endpoints first load the owning historic task via historyService.createHistoricTaskInstanceQuery().taskId(taskId); a null singleResult means the taskId is unknown, the task history was deleted, or scope filtering (task/process/global) excluded it.
Source
Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/task/HistoricTaskInstanceVariableDataResource.java:112
public RestVariable getVariableFromRequest(boolean includeBinary, String taskId, String variableName, String scope) {
RestVariableScope variableScope = RestVariable.getScopeFromString(scope);
HistoricTaskInstanceQuery taskQuery = historyService.createHistoricTaskInstanceQuery().taskId(taskId);
if (variableScope != null) {
if (variableScope == RestVariableScope.GLOBAL) {
taskQuery.includeProcessVariables();
} else {
taskQuery.includeTaskLocalVariables();
}
} else {
taskQuery.includeTaskLocalVariables().includeProcessVariables();
}
HistoricTaskInstance taskObject = taskQuery.singleResult();
if (taskObject == null) {
throw new FlowableObjectNotFoundException("Historic task instance '" + taskId + "' couldn't be found.", HistoricTaskInstanceEntity.class);
}
if (restApiInterceptor != null) {
restApiInterceptor.accessHistoryTaskInfoById(taskObject);
}
Object value = null;
if (variableScope != null) {
if (variableScope == RestVariableScope.GLOBAL) {
value = taskObject.getProcessVariables().get(variableName);
} else {
value = taskObject.getTaskLocalVariables().get(variableName);
}
} else {
// look for local task variables first
if (taskObject.getTaskLocalVariables().containsKey(variableName)) {
value = taskObject.getTaskLocalVariables().get(variableName);
} else {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Verify the taskId exists: GET /cmmn-history/historic-task-instances/{taskId} should return 200 before requesting variables
- Check the scope query parameter — omit it or use the correct scope (task/local vs process/global) so the query includes the right variable set
- Confirm history is persisted: historyLevel must be at least 'audit' and history cleanup must not have purged the task
- If using the REST API against a different deployment/database, confirm you are querying the same Flowable instance that executed the task
Example fix
// before
RestVariable v = get(taskId, varName); // 404 when taskId wrong
// after
HistoricTaskInstance t = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
if (t == null) throw new IllegalArgumentException("unknown historic task " + taskId);
RestVariable v = get(taskId, varName); Defensive patterns
Strategy: validation
Validate before calling
const task = await fetch(`/cmmn-history/historic-task-instances/${taskId}`);
if (task.status === 404) throw new Error(`Historic task ${taskId} not found`);
// only then fetch variables Type guard
async function historicTaskExists(taskId) {
const res = await fetch(`/cmmn-history/historic-task-instances/${taskId}`);
return res.ok;
} Try / catch
try {
return await fetchVariable(taskId, name);
} catch (e) {
if (/Historic task instance '.*' couldn't be found/.test(String(e.message))) {
throw new NotFoundError(`Historic task ${taskId} missing (purged or wrong id)`);
}
throw e;
} Prevention
- Resolve the taskId from the task-creation response and store it, rather than reconstructing it
- Confirm history level is 'audit' or higher so variables are persisted
- Check history cleanup settings — a purged task yields 404 on all variable endpoints
- Omit or correctly set the scope query parameter so the variable include-flags match
When it happens
Trigger: GET /cmmn-history/historic-task-instances/{taskId}/variables/{variableName} (or /data) with a nonexistent taskId, a taskId from a purged/cleaned-up history, or a 'scope' query parameter that doesn't match where the variable lives so include-flags hide it.
Common situations: Typos or wrong-ID prefixes (using a runtime task id after history cleanup, or a processInstanceId instead of taskId); history level configured below 'audit' so nothing was persisted; history cleanup job removed the task before the variable was fetched.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- The variable does not have a binary data stream.
- Unexpected exception getting variable data
- The variable does not have a binary data stream.
- Variable '${restVariable.getName()}' has unsupported type: '
- Invalid variable scope: '${scope}'
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/d2cc813d64fc5f2c.
Report an issue: GitHub.