{"record":{"id":"8ac6a86a61da87b2","repo":"flowable/flowable-engine","slug":"processinstanceids-is-empty","errorCode":null,"errorMessage":"processInstanceIds is empty","messagePattern":"processInstanceIds is empty","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/BulkDeleteHistoricProcessInstancesCmd.java","lineNumber":40,"sourceCode":"import org.flowable.engine.impl.util.CommandContextUtil;\n\npublic class BulkDeleteHistoricProcessInstancesCmd implements Command<Object>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n    protected Collection<String> processInstanceIds;\n\n    public BulkDeleteHistoricProcessInstancesCmd(Collection<String> processInstanceIds) {\n        this.processInstanceIds = processInstanceIds;\n    }\n\n    @Override\n    public Object execute(CommandContext commandContext) {\n        if (processInstanceIds == null) {\n            throw new FlowableIllegalArgumentException(\"processInstanceIds is null\");\n        }\n\n        if (processInstanceIds.isEmpty()) {\n            throw new FlowableIllegalArgumentException(\"processInstanceIds is empty\");\n        }\n        \n        CommandContextUtil.getHistoryManager(commandContext).recordBulkDeleteProcessInstances(processInstanceIds);\n\n        return null;\n    }\n\n}\n","sourceCodeStart":22,"sourceCodeEnd":49,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/BulkDeleteHistoricProcessInstancesCmd.java#L22-L49","documentation":"BulkDeleteHistoricProcessInstancesCmd.execute throws FlowableIllegalArgumentException when the process instance id collection is non-null but empty. An empty list would be a no-op delete, so the engine treats it as an invalid call instead of silently succeeding.","triggerScenarios":"Calling the bulk delete historic process instances API with an empty List (e.g. a query for completed instances returned nothing and the result was passed straight through to the bulk delete).","commonSituations":"Batch jobs that gather finished instance ids then delete their history — on the first run or when no instances match the filter, the list is empty and the call fails; filtering criteria too narrow; scheduler runs before data exists.","solutions":["Guard with an isEmpty() check before calling; skip the bulk delete when the list is empty.","Log when the empty case occurs so batch jobs do not look failed when nothing matched.","Fix upstream query logic if the empty result is unexpected (e.g. wrong historic-level configuration or time window).","Only catch FlowableIllegalArgumentException if an empty batch is legitimately expected and ignorable."],"exampleFix":"// before\nhistoryService.bulkDeleteHistoricProcessInstances(ids); // may be empty\n// after\nif (ids != null && !ids.isEmpty()) {\n    historyService.bulkDeleteHistoricProcessInstances(ids);\n} else {\n    logger.info(\"No historic process instances to delete\");\n}","handlingStrategy":"validation","validationCode":"if (processInstanceIds == null || processInstanceIds.isEmpty()) {\n    logger.info(\"Nothing to delete; skipping bulk historic delete\");\n    return;\n}","typeGuard":null,"tryCatchPattern":"try {\n    historyService.bulkDeleteHistoricProcessInstances(ids);\n} catch (FlowableIllegalArgumentException e) {\n    if (e.getMessage().contains(\"is empty\")) {\n        logger.info(\"Empty id list; nothing deleted\");\n    } else {\n        throw e;\n    }\n}","preventionTips":["Always check isEmpty() before bulk operations.","Make batch jobs log empty batches as informational, not errors.","Review upstream query filters when empty results are unexpected.","Centralize collection guards in a utility method for bulk engine calls."],"tags":["flowable","history","empty-collection","bulk-delete","validation"],"backgroundTag":"empty-required-field","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}