flowable/flowable-engine · error · FlowableIllegalArgumentException
query is null
Error message
query is null
What it means
Thrown by DeleteHistoricCaseInstancesUsingBatchesCmd.execute() when the HistoricCaseInstanceQuery passed to the command is null. The command needs a query to slice case instance ids into batches for deletion; without it no work can be planned.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/delete/DeleteHistoricCaseInstancesUsingBatchesCmd.java:64
*/
public class DeleteHistoricCaseInstancesUsingBatchesCmd implements Command<String> {
protected HistoricCaseInstanceQueryImpl historicCaseInstanceQuery;
protected int batchSize;
protected boolean sequential;
protected String batchName;
public DeleteHistoricCaseInstancesUsingBatchesCmd(HistoricCaseInstanceQueryImpl query, int batchSize, String batchName, boolean sequential) {
this.historicCaseInstanceQuery = query;
this.batchSize = batchSize;
this.batchName = batchName;
this.sequential = sequential;
}
@Override
public String execute(CommandContext commandContext) {
if (historicCaseInstanceQuery == null) {
throw new FlowableIllegalArgumentException("query is null");
}
if (batchSize <= 0) {
throw new FlowableIllegalArgumentException("batchSize has to be larger than 0");
}
CmmnEngineConfiguration engineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
BatchService batchService = engineConfiguration.getBatchServiceConfiguration()
.getBatchService();
long numberOfCaseInstancesToDelete = historicCaseInstanceQuery.count();
ObjectNode batchConfiguration = engineConfiguration.getObjectMapper().createObjectNode();
batchConfiguration.put("numberOfInstances", numberOfCaseInstancesToDelete);
batchConfiguration.put("batchSize", batchSize);
if (sequential) {
batchConfiguration.put("sequential", true);
}View on GitHub (pinned to d6d39ce1c6)
Solutions
- Construct a query first: historyService.createHistoricCaseInstanceQuery() (add filters as needed) and pass it to the command/management method
- Add a null check on the query before invoking the command
- Ensure the code path building the query always executes before the delete call
Example fix
// before HistoricCaseInstanceQuery query = null; managementService.bulkDeleteHistoricCaseInstances(query, 10, true); // after HistoricCaseInstanceQuery query = historyService.createHistoricCaseInstanceQuery().finished(); managementService.bulkDeleteHistoricCaseInstances(query, 10, true);
Defensive patterns
Strategy: type-guard
Validate before calling
if (historicCaseInstanceQuery == null) {
historicCaseInstanceQuery = historyService.createHistoricCaseInstanceQuery();
}
managementService.bulkDeleteHistoricCaseInstances(historicCaseInstanceQuery, batchSize, sequential); Type guard
boolean isUsableQuery(HistoricCaseInstanceQuery q) { return q != null; } Try / catch
try { cmd.execute(commandContext); } catch (FlowableIllegalArgumentException e) { if (e.getMessage().equals("query is null")) { log.error("Pass a created HistoricCaseInstanceQuery", e); } throw e; } Prevention
- Always create the query via historyService.createHistoricCaseInstanceQuery() immediately before the delete call
- Also validate batchSize > 0 in the same guard
- Avoid optional/unassigned query variables across code paths
When it happens
Trigger: Calling the command (or the management-service method wrapping it) with historicCaseInstanceQuery == null, typically by passing an uninitialized variable or skipping query construction.
Common situations: Refactoring that left the query unassigned; conditional code paths where the query build step is skipped; API misuse assuming the command builds its own query.
Related errors
- parentScopeIds is null or empty
- Business status is null
- Case definition keys is null
- tenant id is null
- variableNames is null or empty
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/1c23a9c51f9850b8.
Report an issue: GitHub.