flowable/flowable-engine · error · ActivitiIllegalArgumentException

Invalid historic task id : null

Error message

Invalid historic task id : null

What it means

findHistoricTaskInstanceById requires a non-null task id and fails fast with ActivitiIllegalArgumentException otherwise. It validates arguments before hitting the database and also returns null (rather than throwing) when history is disabled.

Solutions

  1. Ensure the taskId is non-null before calling; fail early in your own code with a clear message.
  2. Null-check optional inputs (e.g., from HTTP params) before querying history.
  3. If the id may legitimately be absent, guard with an existence query first.

Example fix

// before
HistoricTaskInstance t = historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();

// after
if (id == null) throw new IllegalArgumentException("historic task id required");
HistoricTaskInstance t = historyService.createHistoricTaskInstanceQuery().taskId(id).singleResult();
Defensive patterns

Strategy: validation

Validate before calling

if (taskId == null || taskId.isBlank()) {
    throw new IllegalArgumentException("historic task id required");
}

Type guard

function hasHistoricTaskId(params) {
  return typeof params.taskId === 'string' && params.taskId.length > 0;
}

Try / catch

try {
    return historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
} catch (ActivitiIllegalArgumentException e) {
    return null; // or rethrow with your own message
}

Prevention

When it happens

Trigger: Calling HistoryService.createHistoricTaskInstanceQuery()... or the entity manager method with a null taskId; passing a variable that was never initialized; binding an optional path/request parameter that is missing.

Common situations: REST handlers that don't validate the id parameter; code paths after a task lookup returned null and the null was propagated; unit tests exercising historic queries with placeholder nulls.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/persistence/entity/HistoricTaskInstanceEntityManager.java:99

                if (firstResult > 0) {
                    if (firstResult <= instanceList.size()) {
                        int toIndex = firstResult + Math.min(maxResults, instanceList.size() - firstResult);
                        return instanceList.subList(firstResult, toIndex);
                    } else {
                        return Collections.EMPTY_LIST;
                    }
                } else {
                    int toIndex = Math.min(maxResults, instanceList.size());
                    return instanceList.subList(0, toIndex);
                }
            }
        }
        return Collections.EMPTY_LIST;
    }

    public HistoricTaskInstanceEntity findHistoricTaskInstanceById(String taskId) {
        if (taskId == null) {
            throw new ActivitiIllegalArgumentException("Invalid historic task id : null");
        }
        if (getHistoryManager().isHistoryEnabled()) {
            return (HistoricTaskInstanceEntity) getDbSqlSession().selectOne("selectHistoricTaskInstance", taskId);
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public List<HistoricTaskInstance> findHistoricTasksByParentTaskId(String parentTaskId) {
        return getDbSqlSession().selectList("selectHistoricTasksByParentTaskId", parentTaskId);
    }

    public void deleteHistoricTaskInstanceById(String taskId) {
        if (getHistoryManager().isHistoryEnabled()) {
            HistoricTaskInstanceEntity historicTaskInstance = findHistoricTaskInstanceById(taskId);
            if (historicTaskInstance != null) {
                CommandContext commandContext = Context.getCommandContext();

View on GitHub (pinned to d6d39ce1c6)