flowable/flowable-engine · error · FlowableIllegalArgumentException

historic case instanceIds are empty

Error message

historic case instanceIds are empty

What it means

BulkDeleteHistoricCaseInstancesCmd.execute throws FlowableIllegalArgumentException when the caseInstanceIds collection is non-null but empty. An empty batch is treated as a caller mistake (rather than a silent no-op) so users notice that their id selection produced nothing.

Source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/BulkDeleteHistoricCaseInstancesCmd.java:41

public class BulkDeleteHistoricCaseInstancesCmd implements Command<Object>, Serializable {

    private static final long serialVersionUID = 1L;

    protected Collection<String> caseInstanceIds;

    public BulkDeleteHistoricCaseInstancesCmd(Collection<String> caseInstanceIds) {
        this.caseInstanceIds = caseInstanceIds;
    }

    @Override
    public Object execute(CommandContext commandContext) {
        if (caseInstanceIds == null) {
            throw new FlowableIllegalArgumentException("historic case instanceIds are null");
        }

        if (caseInstanceIds.isEmpty()) {
            throw new FlowableIllegalArgumentException("historic case instanceIds are empty");
        }
        
        CommandContextUtil.getCmmnHistoryManager(commandContext).recordBulkDeleteHistoricCaseInstances(caseInstanceIds);
        
        return null;
    }

}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Guard in caller code: skip the bulk delete when the id list is empty
  2. Fix the selection/query that produced the empty batch if ids were expected
  3. Treat empty input as no-op instead of calling the API

Example fix

// before
historyService.bulkDeleteHistoricCaseInstances(ids);
// after
if (!ids.isEmpty()) {
    historyService.bulkDeleteHistoricCaseInstances(ids);
}
Defensive patterns

Strategy: validation

Validate before calling

if (ids == null || ids.isEmpty()) { return; /* skip as no-op */ }

Try / catch

try {
    historyService.bulkDeleteHistoricCaseInstances(ids);
} catch (FlowableIllegalArgumentException e) {
    log.warn("Nothing to delete: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Calling bulkDeleteHistoricCaseInstances with a zero-element list — e.g. a query for case instances closed before a date that matched nothing, or filtering that removed all ids before the call.

Common situations: Scheduled cleanup with over-aggressive date filters; UI passing an empty selection because no rows were checked; test fixtures with no historic data.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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