flowable/flowable-engine · error · FlowableObjectNotFoundException

Historic task instance '' variable value for couldn't be fo

Error message

Historic task instance '' variable value for  couldn't be found.

What it means

Thrown by the CMMN REST API when a historic task variable lookup returns nothing: GET history/historic-task-instances/{taskId}/variables/{variableName} resolved no variable with that name on the historic task instance. Flowable wraps this as FlowableObjectNotFoundException because the requested historic variable resource does not exist, so the endpoint returns a 404 with this message. It is a lookup miss, not a data corruption or permission issue.

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/history/task/HistoricTaskInstanceVariableDataResource.java:136

        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 {
                value = taskObject.getProcessVariables().get(variableName);
            }
        }

        if (value == null) {
            throw new FlowableObjectNotFoundException("Historic task instance '" + taskId + "' variable value for " + variableName + " couldn't be found.", VariableInstanceEntity.class);
        } else {
            return restResponseFactory.createRestVariable(variableName, value, null, taskId, CmmnRestResponseFactory.VARIABLE_HISTORY_TASK, includeBinary);
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the taskId exists via GET /cmmn-history/historic-task-instances/{taskId} before fetching a variable.
  2. List all variables first with GET /cmmn-history/historic-task-instances/{taskId}/variables and use an exact name from the response.
  3. Check for typos/case differences in variableName; historic variable names are matched exactly.
  4. Confirm the variable was actually set on the task before it completed (runtime variable set after completion never lands in history).
  5. If the variable may legitimately be absent, catch FlowableObjectNotFoundException and treat it as an empty value instead of a failure.

Example fix

// before: direct fetch that 404s on missing name
RestVariable v = client.getHistoricTaskVariable(taskId, "approver");

// after: tolerate absence
try {
    RestVariable v = client.getHistoricTaskVariable(taskId, "approver");
} catch (FlowableObjectNotFoundException e) {
    String approver = null; // variable not in history
}
Defensive patterns

Strategy: try-catch

Validate before calling

// resolve and check first
HistoricTaskInstance t = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
if (t == null || t.getProcessVariables() == null || !t.getProcessVariables().containsKey(variableName)) {
    // skip the variable fetch or use a default
}

Type guard

boolean hasHistoricVariable(HistoricTaskInstance t, String name) {
    return t != null && t.getVariables() != null && t.getVariables().containsKey(name);
}

Try / catch

try {
    RestVariable v = resource.getVariable(taskId, variableName);
} catch (FlowableObjectNotFoundException e) {
    // HTTP 404: variable not present in history; use default/null
}

Prevention

When it happens

Trigger: GET /cmmn-history/historic-task-instances/{taskId}/variables/{variableName} where the historic task exists but has no completed/persisted variable with that exact name, the variable was set and deleted before task completion, the taskId does not exist at all, or the variable name is misspelled / differs in case.

Common situations: Developers query a variable that only exists at runtime (set after the task finished), use the case-task variable name instead of the stored name, hit the CMMN history endpoint expecting process-engine semantics, or test against an in-memory H2 database that was recreated between calls so history is empty.

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


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