flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find a task instance with id '${taskId}'.

Error message

Could not find a task instance with id '${taskId}'.

What it means

FlowableObjectNotFoundException thrown when a historic task instance cannot be found for the supplied taskId. getHistoricTaskInstanceFromRequestWithoutAccessCheck performs the lookup via HistoricTaskInstanceQuery and throws when no row matches; shared by many historic-task REST endpoints. Note this path skips the access interceptor check.

Source

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

     */
    protected HistoricTaskInstance getHistoricTaskInstanceFromRequest(String taskId) {
        HistoricTaskInstance taskInstance = getHistoricTaskInstanceFromRequestWithoutAccessCheck(taskId);

        if (restApiInterceptor != null) {
            restApiInterceptor.accessHistoryTaskInfoById(taskInstance);
        }
        
        return taskInstance;
    }

    /**
     * Returns the {@link HistoricTaskInstance} that is requested without calling the access interceptor
     * Throws the right exceptions when bad request was made or instance was not found.
     */
    protected HistoricTaskInstance getHistoricTaskInstanceFromRequestWithoutAccessCheck(String taskId) {
        HistoricTaskInstance taskInstance = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
        if (taskInstance == null) {
            throw new FlowableObjectNotFoundException("Could not find a task instance with id '" + taskId + "'.", HistoricTaskInstance.class);
        }
        
        return taskInstance;
    }

    protected void addTaskVariables(HistoricTaskInstanceQuery taskInstanceQuery, List<QueryVariable> variables) {
        for (QueryVariable variable : variables) {
            if (variable.getVariableOperation() == null) {
                throw new FlowableIllegalArgumentException("Variable operation is missing for variable: " + variable.getName());
            }
            if (variable.getVariableOperation() != QueryVariableOperation.EXISTS && variable.getVariableOperation() != QueryVariableOperation.NOT_EXISTS) {
                if (variable.getValue() == null) {
                    throw new FlowableIllegalArgumentException("Variable value is missing for variable: " + variable.getName());
                }
            }

            boolean nameLess = variable.getName() == null;

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Confirm the task exists via GET /cmmn-history/historic-task-instances with query filters and copy the exact historic task id.
  2. Catch FlowableObjectNotFoundException and map it to HTTP 404.
  3. Check the history cleanup configuration and retention period.
  4. Verify you are not passing a runtime task id to a history-only endpoint after process completion.
  5. Confirm the correct Flowable engine/datasource is being queried.

Example fix

// before
HistoricTaskInstance t = historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
// after
HistoricTaskInstance t = historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
if (t == null) {
    return ResponseEntity.notFound().build();
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure the id exists in history before use
List<HistoricTaskInstanceResponse> hits = query("/cmmn-history/historic-task-instances?taskId=" + id);

Try / catch

try {
    HistoricTaskInstanceResponse t = getHistoricTask(id);
} catch (FlowableObjectNotFoundException e) {
    return ResponseEntity.notFound().build();
}

Prevention

When it happens

Trigger: Any GET on /cmmn-history/historic-task-instances/{taskId} (or sub-resources like variables/identity links) where the taskId does not match a historic task row - task purged by history cleanup, wrong database, or a runtime task id passed where only historic ids are valid.

Common situations: Using the runtime Task id after task completion; history cleaner removed old records; typo'd or fabricated ids; querying the wrong engine datasource in multi-datasource setups.

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/ee25a92cfedfa562. Report an issue: GitHub.