flowable/flowable-engine · error · ActivitiIllegalArgumentException

Invalid task id : null

Error message

Invalid task id : null

What it means

TaskEntityManager.findTaskById validates its argument and throws ActivitiIllegalArgumentException when the id is null before querying the database. This is a fail-fast guard: a null id would produce a meaningless or dangerous selectById. Note this is an IllegalArgumentException, not a generic ActivitiException, so catch accordingly.

Solutions

  1. Null-check the task id in your code before calling any task lookup API
  2. Trace where the id comes from (form field, process variable, REST param) and require it at the boundary
  3. Catch ActivitiIllegalArgumentException and return a 400-style validation error to the caller

Example fix

// before
Task task = taskService.createTaskQuery().taskId(requestParam).singleResult();
// after
if (requestParam == null || requestParam.isEmpty()) {
    throw new BadRequestException("taskId is required");
}
Task task = taskService.createTaskQuery().taskId(requestParam).singleResult();
Defensive patterns

Strategy: validation

Validate before calling

if (taskId == null || taskId.trim().isEmpty()) throw new IllegalArgumentException("taskId required");

Type guard

boolean isValidTaskId(String id) { return id != null && !id.trim().isEmpty(); }

Try / catch

try {
    Task t = taskService.createTaskQuery().taskId(taskId).singleResult();
} catch (ActivitiIllegalArgumentException e) {
    throw new BadRequestException("taskId must be provided");
}

Prevention

When it happens

Trigger: Calling taskService.createTaskQuery().taskId(null), TaskService-related APIs, or any engine path (including deleteTask with a null taskId) that resolves a task by id when the id variable is null/uninitialized.

Common situations: taskId taken from an unset request parameter or missing path variable; a variable holding the task id was never set in the process; deserialization produced a null id; copy/paste of query code with placeholder nulls.

Related errors


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

Appendix: source

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

            } else {
                commandContext
                        .getHistoryManager()
                        .recordTaskEnd(taskId, deleteReason);
            }

            getDbSqlSession().delete(task);

            if (commandContext.getEventDispatcher().isEnabled()) {
                commandContext.getEventDispatcher().dispatchEvent(
                        ActivitiEventBuilder.createEntityEvent(FlowableEngineEventType.ENTITY_DELETED, task),
                        EngineConfigurationConstants.KEY_PROCESS_ENGINE_CONFIG);
            }
        }
    }

    public TaskEntity findTaskById(String id) {
        if (id == null) {
            throw new ActivitiIllegalArgumentException("Invalid task id : null");
        }
        return (TaskEntity) getDbSqlSession().selectById(TaskEntity.class, id);
    }

    @SuppressWarnings("unchecked")
    public List<TaskEntity> findTasksByExecutionId(String executionId) {
        return getDbSqlSession().selectList("selectTasksByExecutionId", executionId);
    }

    @SuppressWarnings("unchecked")
    public List<TaskEntity> findTasksByProcessInstanceId(String processInstanceId) {
        return getDbSqlSession().selectList("selectTasksByProcessInstanceId", processInstanceId);
    }

    @Deprecated
    public List<Task> findTasksByQueryCriteria(TaskQueryImpl taskQuery, Page page) {
        taskQuery.setFirstResult(page.getFirstResult());
        taskQuery.setMaxResults(page.getMaxResults());

View on GitHub (pinned to d6d39ce1c6)