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

  1. Verify the taskId exists: GET /cmmn-history/historic-task-instances/{taskId} should return 200 before requesting variables
  2. 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
  3. Confirm history is persisted: historyLevel must be at least 'audit' and history cleanup must not have purged the task
  4. 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

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


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/d2cc813d64fc5f2c. Report an issue: GitHub.