{"record":{"id":"32aae0fbc3df9a49","repo":"flowable/flowable-engine","slug":"deleting-historic-process-instances-with-related-d","errorCode":null,"errorMessage":"deleting historic process instances with related data requires CommandExecutor","messagePattern":"deleting historic process instances with related data requires CommandExecutor","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricProcessInstanceQueryImpl.java","lineNumber":1296,"sourceCode":"    @Override\n    public void delete() {\n        if (commandExecutor != null) {\n            commandExecutor.execute(new DeleteHistoricProcessInstancesCmd(this));\n        } else {\n            new DeleteHistoricProcessInstancesCmd(this).execute(Context.getCommandContext());\n        }\n    }\n\n    @Override\n    @Deprecated\n    public void deleteWithRelatedData() {\n        if (commandExecutor != null) {\n            CommandConfig config = new CommandConfig().transactionRequiresNew();\n            commandExecutor.execute(config, new DeleteHistoricProcessInstancesCmd(this));\n            commandExecutor.execute(config, new DeleteTaskAndActivityDataOfRemovedHistoricProcessInstancesCmd());\n            commandExecutor.execute(config, new DeleteRelatedDataOfRemovedHistoricProcessInstancesCmd());\n        } else {\n            throw new FlowableException(\"deleting historic process instances with related data requires CommandExecutor\");\n        }\n    }\n\n    @Override\n    public String deleteInParallelUsingBatch(int batchSize, String batchName) {\n        return commandExecutor.execute(new DeleteHistoricProcessInstancesUsingBatchesCmd(this, batchSize, batchName, false));\n    }\n\n    @Override\n    public String deleteSequentiallyUsingBatch(int batchSize, String batchName) {\n        return commandExecutor.execute(new DeleteHistoricProcessInstancesUsingBatchesCmd(this, batchSize, batchName, true));\n    }\n\n    public String getBusinessKey() {\n        return businessKey;\n    }\n\n    public String getBusinessKeyLike() {","sourceCodeStart":1278,"sourceCodeEnd":1314,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/HistoricProcessInstanceQueryImpl.java#L1278-L1314","documentation":"Flowable throws this FlowableException from HistoricProcessInstanceQueryImpl.delete when deleting historic process instances with related data but the query was constructed without a CommandExecutor. Deleting related data (tasks, activity data, related content) is executed as separate REQUIRES_NEW commands that need a real command executor; a detached query built manually has none.","triggerScenarios":"Calling query.delete() on a HistoricProcessInstanceQueryImpl created with the no-arg/partial constructor (no commandExecutor injected) instead of obtaining the query from runtimeService.createHistoricProcessInstanceQuery().","commonSituations":"Unit tests or custom code instantiating HistoricProcessInstanceQueryImpl directly with new and invoking delete; deserializing a query object and calling delete without wiring the engine services.","solutions":["Obtain the query via processEngine.getHistoryService().createHistoricProcessInstanceQuery() so it carries the engine's CommandExecutor","If constructing manually, use a constructor that accepts the CommandContext or CommandExecutor","In tests, build the query from a real ProcessEngine (or mock the command executor) before calling delete"],"exampleFix":"// before\nHistoricProcessInstanceQueryImpl q = new HistoricProcessInstanceQueryImpl();\nq.delete();\n// after\nHistoricProcessInstanceQuery q = historyService.createHistoricProcessInstanceQuery()\n    .finishedBefore(date);\nq.delete();","handlingStrategy":"validation","validationCode":"if (query instanceof HistoricProcessInstanceQueryImpl\n        && ((HistoricProcessInstanceQueryImpl) query).getCommandExecutor() == null) {\n    throw new IllegalStateException(\"Query must be created via HistoryService to support delete()\");\n}","typeGuard":"boolean isDeletableQuery(HistoricProcessInstanceQuery q) {\n    return q instanceof HistoricProcessInstanceQueryImpl\n        && ((HistoricProcessInstanceQueryImpl) q).getCommandExecutor() != null;\n}","tryCatchPattern":"try {\n    query.delete();\n} catch (FlowableException e) {\n    throw new IllegalStateException(\"Rebuild the query via historyService.createHistoricProcessInstanceQuery()\", e);\n}","preventionTips":["Always obtain queries from HistoryService rather than instantiating HistoricProcessInstanceQueryImpl directly","Never call delete() on manually constructed or deserialized query objects","In tests, build queries through a real ProcessEngine-backed service"],"tags":["flowable","delete","command-executor","initialization"],"backgroundTag":"missing-dependency","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}