flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find a job with id ''.

Error message

Could not find a job with id ''.

What it means

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.

Source

Thrown at modules/flowable-cmmn-rest/src/main/java/org/flowable/cmmn/rest/service/api/management/JobBaseResource.java:66

        validateJob(job, jobId);
        return job;
    }

    protected Job getDeadLetterJobById(String jobId) {
        Job job = managementService.createDeadLetterJobQuery().jobId(jobId).singleResult();
        validateJob(job, jobId);
        return job;
    }

    protected HistoryJob getHistoryJobById(String jobId) {
        HistoryJob job = managementService.createHistoryJobQuery().jobId(jobId).singleResult();
        validateHistoryJob(job, jobId);
        return job;
    }
    
    protected void validateJob(Job job, String jobId) {
        if (job == null) {
            throw new FlowableObjectNotFoundException("Could not find a job with id '" + jobId + "'.", Job.class);
        }
        
        if (restApiInterceptor != null) {
            restApiInterceptor.accessJobInfoById(job);
        }
    }

    protected void validateHistoryJob(HistoryJob job, String jobId) {
        if (job == null) {
            throw new FlowableObjectNotFoundException("Could not find a history job with id '" + jobId + "'.", HistoryJob.class);
        }

        if (restApiInterceptor != null) {
            restApiInterceptor.accessHistoryJobInfoById(job);
        }
    }
}

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Verify the job id from a fresh list of the relevant job collection.
  2. Check the correct engine/database and correct endpoint type (job vs timer vs dead letter).
  3. Handle 404 from these endpoints as 'job no longer exists' — for retry logic, re-query instead of retrying the same id.

Example fix

// before
Job job = jobBaseResource.getJobById(staleId);
// after
DeadLetterJobResponse job = firstOrNull(client.get("/cmmn-management/deadletter-jobs"));
if (job == null) { skip(); } else { use(job.getId()); }
Defensive patterns

Strategy: try-catch

Validate before calling

// no pre-call validation possible beyond non-blank id
if (!jobId || jobId.trim() === "") throw new Error("jobId required");

Try / catch

try { job = getJob(id) } catch (e) { if (e.status === 404) { refreshJobList(); return; } throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/76e3287948926f0f. Report an issue: GitHub.