{"record":{"id":"ee597811fb76fe67","repo":"flowable/flowable-engine","slug":"query-is-null-ee5978","errorCode":null,"errorMessage":"query is null","messagePattern":"query is null","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/DeleteHistoricProcessInstancesCmd.java","lineNumber":36,"sourceCode":"import org.flowable.common.engine.api.FlowableIllegalArgumentException;\nimport org.flowable.common.engine.impl.interceptor.Command;\nimport org.flowable.common.engine.impl.interceptor.CommandContext;\nimport org.flowable.engine.impl.HistoricProcessInstanceQueryImpl;\nimport org.flowable.engine.impl.util.CommandContextUtil;\n\npublic class DeleteHistoricProcessInstancesCmd implements Command<Object>, Serializable {\n\n    private static final long serialVersionUID = 1L;\n    protected HistoricProcessInstanceQueryImpl historicProcessInstanceQuery;\n\n    public DeleteHistoricProcessInstancesCmd(HistoricProcessInstanceQueryImpl historicProcessInstanceQuery) {\n        this.historicProcessInstanceQuery = historicProcessInstanceQuery;\n    }\n\n    @Override\n    public Object execute(CommandContext commandContext) {\n        if (historicProcessInstanceQuery == null) {\n            throw new FlowableIllegalArgumentException(\"query is null\");\n        }\n        \n        CommandContextUtil.getHistoricProcessInstanceEntityManager(commandContext).deleteHistoricProcessInstances(historicProcessInstanceQuery);\n\n        return null;\n    }\n\n}\n","sourceCodeStart":18,"sourceCodeEnd":45,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/DeleteHistoricProcessInstancesCmd.java#L18-L45","documentation":"DeleteHistoricProcessInstancesCmd bulk-deletes historic process instances matching a HistoricProcessInstanceQuery; it validates the query object is non-null. A null query means nothing to evaluate, so the engine throws FlowableIllegalArgumentException immediately.","triggerScenarios":"historyService.deleteHistoricProcessInstances(query) (or the bulk variant via management APIs) where the query variable is null, e.g. a builder method returned null or a field was never initialized before deletion.","commonSituations":"Programmatic query construction where a branch skips creating the query, refactoring that removed query creation, or passing null intentionally as 'delete all' which the API does not accept.","solutions":["Create a query object first: historyService.createHistoricProcessInstanceQuery() and apply criteria before passing it","Guard the call with a null check on the query","Initialize the query field at construction instead of lazily"],"exampleFix":"// before\nhistoryService.deleteHistoricProcessInstances(query); // query was null\n// after\nHistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery()\n    .finished().before(new Date());\nhistoryService.deleteHistoricProcessInstances(query);","handlingStrategy":"validation","validationCode":"if (query == null) {\n    throw new IllegalArgumentException(\"A HistoricProcessInstanceQuery is required for bulk delete\");\n}","typeGuard":"boolean isValidQuery = q -> q instanceof HistoricProcessInstanceQuery;","tryCatchPattern":"try {\n    historyService.deleteHistoricProcessInstances(query);\n} catch (FlowableIllegalArgumentException e) {\n    logger.error(\"Bulk delete called without a query\", e);\n}","preventionTips":["Build the query in the same scope as the delete call","Never pass null as a 'delete all' shorthand; there is no such API","Initialize query fields eagerly in classes that own deletion logic"],"tags":["flowable","null-argument","history","bulk-delete"],"backgroundTag":"null-argument","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"}