{"record":{"id":"2c13c7e1214e4a97","repo":"flowable/flowable-engine","slug":"jobid-is-null-2c13c7","errorCode":null,"errorMessage":"jobId is null","messagePattern":"jobId is null","errorType":"validation","errorClass":"FlowableIllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/DeleteHistoryJobCmd.java","lineNumber":68,"sourceCode":"        HistoryJobEntity jobToDelete = getJobToDelete(commandContext);\n\n        sendCancelEvent(jobToDelete);\n\n        jobServiceConfiguration.getHistoryJobEntityManager().delete(jobToDelete);\n        return null;\n    }\n\n    protected void sendCancelEvent(HistoryJobEntity jobToDelete) {\n        FlowableEventDispatcher eventDispatcher = jobServiceConfiguration.getEventDispatcher();\n        if (eventDispatcher != null && eventDispatcher.isEnabled()) {\n            eventDispatcher.dispatchEvent(FlowableJobEventBuilder.createEntityEvent(FlowableEngineEventType.JOB_CANCELED, jobToDelete),\n                    jobServiceConfiguration.getEngineName());\n        }\n    }\n\n    protected HistoryJobEntity getJobToDelete(CommandContext commandContext) {\n        if (historyJobId == null) {\n            throw new FlowableIllegalArgumentException(\"jobId is null\");\n        }\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"Deleting job {}\", historyJobId);\n        }\n\n        HistoryJobEntity job = jobServiceConfiguration.getHistoryJobEntityManager().findById(historyJobId);\n        if (job == null) {\n            throw new FlowableObjectNotFoundException(\"No history job found with id '\" + historyJobId + \"'\", Job.class);\n        }\n\n        return job;\n    }\n\n}\n","sourceCodeStart":50,"sourceCodeEnd":83,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/DeleteHistoryJobCmd.java#L50-L83","documentation":"DeleteHistoryJobCmd.getJobToDelete validates that historyJobId is non-null before querying the HistoryJobEntityManager. A null id results in FlowableIllegalArgumentException(\"jobId is null\"). The command refuses to run a database lookup with an empty identifier.","triggerScenarios":"Executing DeleteHistoryJobCmd constructed with a null history job id, typically from API helpers where the id variable was never populated (e.g. a history job query returned no results and the code deleted a null id anyway).","commonSituations":"Async history cleanup scripts that iterate optional query results without checking for null; configuration where async history is disabled so no history jobs exist but code still attempts deletion; copy-pasted delete code using the wrong variable.","solutions":["Only build and execute DeleteHistoryJobCmd with an id obtained from a successful history job query result.","Add a null/blank guard in the calling code to fail with a contextual message naming the source of the id.","If history jobs may not exist, query historyJobEntityManager (or the history job query API) first and skip the delete when empty.","Review recent refactors of the delete call for swapped/lost constructor arguments."],"exampleFix":"// before\nHistoryJobEntity job = ...; // may be null\nmanagementService.executeCommand(new DeleteHistoryJobCmd(job != null ? job.getId() : null));\n// after\nHistoryJobEntity job = ...;\nif (job != null) {\n    managementService.executeCommand(new DeleteHistoryJobCmd(job.getId()));\n}","handlingStrategy":"validation","validationCode":"if (historyJobId == null || historyJobId.isBlank()) {\n    throw new IllegalArgumentException(\"historyJobId is required\");\n}","typeGuard":"boolean hasHistoryJobId(String id) { return id != null && !id.isBlank(); }","tryCatchPattern":"try {\n    managementService.executeCommand(new DeleteHistoryJobCmd(historyJobId));\n} catch (FlowableIllegalArgumentException e) {\n    LOGGER.error(\"History job id missing: {}\", e.getMessage());\n}","preventionTips":["Only derive ids from non-null query results.","Guard optional id sources (variables, maps) before command construction.","Check async history is enabled if you expect history jobs to exist."],"tags":["flowable","history-job","null-argument"],"backgroundTag":"null-argument","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}