{"record":{"id":"c74b7a40a47e5bf1","repo":"flowable/flowable-engine","slug":"no-dead-letter-job-found-with-id","errorCode":null,"errorMessage":"No dead letter job found with id '","messagePattern":"No dead letter 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/DeleteDeadLetterJobCmd.java","lineNumber":76,"sourceCode":"    protected void sendCancelEvent(DeadLetterJobEntity 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 DeadLetterJobEntity getJobToDelete(CommandContext commandContext) {\n        if (deadLetterJobId == null) {\n            throw new FlowableIllegalArgumentException(\"jobId is null\");\n        }\n        if (LOGGER.isDebugEnabled()) {\n            LOGGER.debug(\"Deleting job {}\", deadLetterJobId);\n        }\n\n        DeadLetterJobEntity job = jobServiceConfiguration.getDeadLetterJobEntityManager().findById(deadLetterJobId);\n        if (job == null) {\n            throw new FlowableObjectNotFoundException(\"No dead letter job found with id '\" + deadLetterJobId + \"'\", Job.class);\n        }\n\n        return job;\n    }\n\n}\n","sourceCodeStart":58,"sourceCodeEnd":83,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/DeleteDeadLetterJobCmd.java#L58-L83","documentation":"DeleteDeadLetterJobCmd looks up a dead letter job by id via the DeadLetterJobEntityManager before deleting it. When no row exists with that id, Flowable throws FlowableObjectNotFoundException carrying the id and referencing Job.class. This is the engine telling you the delete was invoked against an id that does not exist in the ACT_RU_DEADLETTER_JOB table.","triggerScenarios":"Calling ManagementService.executeCommand(new DeleteDeadLetterJobCmd(deadLetterJobId)) or an API that delegates to it (e.g. managementService.deleteJob on a dead-letter id) when the dead letter job was already deleted, never existed, or the id string is wrong/typo'd.","commonSituations":"Double-processing of an async failed job (one worker deletes the dead letter job, a retry path deletes it again); deleting after moving the job back to the timer/job tables; using an id from a different engine/process instance; stale UI listing after the job was resolved.","solutions":["Fetch the dead letter job first (managementService.getDeadLetterJobs / createDeadLetterJobQuery().deadLetterJobId(id)) and confirm the id exists before deleting.","Verify you are not deleting the same job twice (guard with an existence check or idempotent handling of FlowableObjectNotFoundException).","Check the job may have been moved out of the dead letter table (retried via moveDeadLetterJobToExecutableJobCmd) — delete from its current table instead.","Log the raw id and compare with the database row in ACT_RU_DEADLETTER_JOB to rule out id truncation or wrong-engine lookup."],"exampleFix":"// before\nmanagementService.executeCommand(new DeleteDeadLetterJobCmd(deadLetterJobId));\n// after\nif (managementService.createDeadLetterJobQuery().deadLetterJobId(deadLetterJobId).count() > 0) {\n    managementService.executeCommand(new DeleteDeadLetterJobCmd(deadLetterJobId));\n}","handlingStrategy":"validation","validationCode":"if (deadLetterJobId == null || managementService.createDeadLetterJobQuery().deadLetterJobId(deadLetterJobId).count() == 0) {\n    throw new IllegalArgumentException(\"Dead letter job does not exist: \" + deadLetterJobId);\n}","typeGuard":null,"tryCatchPattern":"try {\n    managementService.executeCommand(new DeleteDeadLetterJobCmd(deadLetterJobId));\n} catch (FlowableObjectNotFoundException e) {\n    LOGGER.info(\"Dead letter job {} already gone\", deadLetterJobId);\n}","preventionTips":["Always resolve the id from a fresh dead letter job query right before deleting.","Make cleanup routines idempotent against not-found.","Log the id and engine name to catch cross-engine/wrong-table mistakes."],"tags":["flowable","job-management","not-found"],"backgroundTag":"record-not-found","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"}