{"record":{"id":"76e3287948926f0f","repo":"flowable/flowable-engine","slug":"could-not-find-a-job-with-id","errorCode":null,"errorMessage":"Could not find a job with id ''.","messagePattern":"Could not find a job with id ''\\.","errorType":"http","errorClass":"FlowableObjectNotFoundException","httpStatus":404,"severity":"error","filePath":"modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobBaseResource.java","lineNumber":66,"sourceCode":"        validateJob(job, jobId);\n        return job;\n    }\n\n    protected Job getDeadLetterJobById(String jobId) {\n        Job job = managementService.createDeadLetterJobQuery().jobId(jobId).singleResult();\n        validateJob(job, jobId);\n        return job;\n    }\n\n    protected HistoryJob getHistoryJobById(String jobId) {\n        HistoryJob job = managementService.createHistoryJobQuery().jobId(jobId).singleResult();\n        validateHistoryJob(job, jobId);\n        return job;\n    }\n    \n    protected void validateJob(Job job, String jobId) {\n        if (job == null) {\n            throw new FlowableObjectNotFoundException(\"Could not find a job with id '\" + jobId + \"'.\", Job.class);\n        }\n        \n        if (restApiInterceptor != null) {\n            restApiInterceptor.accessJobInfoById(job);\n        }\n    }\n\n    protected void validateHistoryJob(HistoryJob job, String jobId) {\n        if (job == null) {\n            throw new FlowableObjectNotFoundException(\"Could not find a history job with id '\" + jobId + \"'.\", HistoryJob.class);\n        }\n\n        if (restApiInterceptor != null) {\n            restApiInterceptor.accessHistoryJobInfoById(job);\n        }\n    }\n}\n","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobBaseResource.java#L48-L84","documentation":"JobBaseResource.validateJob throws FlowableObjectNotFoundException when the management service query returns no job for the given id, embedding the requested id in the message. It guards endpoints returning job details for jobs/timer jobs/suspended jobs/dead letter jobs.","triggerScenarios":"GET /cmmn-management/jobs/{jobId} (or timer-jobs/suspended-jobs/deadletter-jobs variants) with an id that does not exist, was already executed/deleted, or belongs to a different engine.","commonSituations":"Job executed and removed between listing and fetching; stale ids in scripts/retries; querying a CMMN job id via the BPM REST API or vice versa; typo in id.","solutions":["Verify the job id from a fresh list of the relevant job collection.","Check the correct engine/database and correct endpoint type (job vs timer vs dead letter).","Handle 404 from these endpoints as 'job no longer exists' — for retry logic, re-query instead of retrying the same id."],"exampleFix":"// before\nJob job = jobBaseResource.getJobById(staleId);\n// after\nDeadLetterJobResponse job = firstOrNull(client.get(\"/cmmn-management/deadletter-jobs\"));\nif (job == null) { skip(); } else { use(job.getId()); }","handlingStrategy":"try-catch","validationCode":"// no pre-call validation possible beyond non-blank id\nif (!jobId || jobId.trim() === \"\") throw new Error(\"jobId required\");","typeGuard":null,"tryCatchPattern":"try { job = getJob(id) } catch (e) { if (e.status === 404) { refreshJobList(); return; } throw e; }","preventionTips":["Fetch job ids from a fresh list immediately before use.","Don't reuse ids across engine types (job vs timer vs deadletter) or engines.","Expect jobs to disappear once executed — design retry logic around re-querying."],"tags":["rest-api","resource-not-found","jobs"],"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-14T11:17:12.474Z"}