{"record":{"id":"509e09fe5429b265","repo":"flowable/flowable-engine","slug":"no-timer-job-found-with-id","errorCode":null,"errorMessage":"No timer job found with id '","messagePattern":"No timer job found with id '","errorType":"exception","errorClass":"FlowableObjectNotFoundException","httpStatus":null,"severity":"error","filePath":"modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/DeleteTimerJobCmd.java","lineNumber":76,"sourceCode":"    protected void sendCancelEvent(CommandContext commandContext, TimerJobEntity 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 TimerJobEntity getJobToDelete(CommandContext commandContext) {\n        if (timerJobId == null) {\n            throw new FlowableIllegalArgumentException(\"jobId is null\");\n        }\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"Deleting job {}\", timerJobId);\n        }\n\n        TimerJobEntity job = jobServiceConfiguration.getTimerJobEntityManager().findById(timerJobId);\n        if (job == null) {\n            throw new FlowableObjectNotFoundException(\"No timer job found with id '\" + timerJobId + \"'\", Job.class);\n        }\n\n        // We need to check if the job was locked, ie acquired by the job acquisition thread\n        // This happens if the job was already acquired, but not yet executed.\n        // In that case, we can't allow to delete the job.\n        if (job.getLockOwner() != null) {\n            throw new FlowableException(\"Cannot delete \" + job + \" when the job is being executed. Try again later.\");\n        }\n        return job;\n    }\n\n}\n","sourceCodeStart":58,"sourceCodeEnd":89,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/DeleteTimerJobCmd.java#L58-L89","documentation":"DeleteTimerJobCmd looks up the timer job by id via TimerJobEntityManager.findById; when no row matches it throws FlowableObjectNotFoundException carrying Job.class as the type. It means the id is well-formed but no timer job with that id exists (or it no longer exists).","triggerScenarios":"managementService.deleteTimerJob(id) with an id that was already deleted, a job id (not timer job id) from the ACT_RU_JOB table, an id from another engine/database, or a stale id after the timer fired and moved/disappeared.","commonSituations":"Deleting a timer that already fired (timer jobs move to job/dead-letter tables or vanish when the execution ends); clustered setups where the id exists on another node's database; tests reusing recorded ids across cleanups; passing a TimerJobEntity.getId() after the entity was deleted.","solutions":["Query the id first (managementService.createTimerJobQuery().timerJobId(id).singleResult()) and skip deletion when null.","Catch FlowableObjectNotFoundException and treat the delete as already-done idempotently.","Verify you are connected to the same database/engine the timer job was created in.","Confirm you are not confusing job ids (ACT_RU_JOB) with timer job ids (ACT_RU_TIMER_JOB)."],"exampleFix":"// before\nmanagementService.deleteTimerJob(timerJobId); // throws if already gone\n// after\nif (managementService.createTimerJobQuery().timerJobId(timerJobId).count() > 0) {\n    managementService.deleteTimerJob(timerJobId);\n}","handlingStrategy":"try-catch","validationCode":"boolean exists = managementService.createTimerJobQuery().timerJobId(timerJobId).count() > 0;","typeGuard":null,"tryCatchPattern":"try { managementService.deleteTimerJob(id); } catch (FlowableObjectNotFoundException e) { LOGGER.info(\"Timer job {} already gone\", id); }","preventionTips":["Treat deletes as idempotent: catching not-found is usually correct for cleanup flows.","Distinguish job vs timer-job vs dead-letter ids; each lives in its own table.","Verify engine/database consistency in clustered deployments."],"tags":["flowable","job-service","timer-job","not-found"],"backgroundTag":"entity-not-found","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"}