flowable/flowable-engine · error · FlowableObjectNotFoundException

No External Worker job found for id:

Error message

No External Worker job found for id: 

What it means

Thrown by resolveJob() as a FlowableObjectNotFoundException when findById(externalJobId) returns no ExternalWorkerJobEntity. The job id was well-formed but no matching external worker job row exists anymore — typically because the job was already completed, deleted, or the id is wrong or from another database/tenant.

Solutions

  1. Treat this as an expected race: catch FlowableObjectNotFoundException and skip/ack the job as already handled
  2. Verify the job id and database/tenant the command runs against match the acquisition
  3. Check job retention: if jobs complete too fast, ensure your worker fetches fresh ids rather than caching them

Example fix

// before
externalWorkerJobCompletionBuilder.externalJobId(jobId).workerId(workerId).complete();
// after
try {
    externalWorkerJobCompletionBuilder.externalJobId(jobId).workerId(workerId).complete();
} catch (FlowableObjectNotFoundException e) {
    LOGGER.info("External worker job {} already gone, skipping", jobId);
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
    completionBuilder.externalJobId(jobId).workerId(workerId).complete();
} catch (FlowableObjectNotFoundException e) {
    LOGGER.info("Job {} no longer exists (already completed/deleted), skipping", jobId);
}

Prevention

When it happens

Trigger: Calling completeExternalWorkerJob/terminateExternalWorkerJob/failExternalWorkerJob with a job id that was deleted after completion; a stale job reference held across a long worker outage; typo'd or cross-environment job id; job removed by cleanup/history jobs in the meantime.

Common situations: Long-running worker holds an id while another worker instance completed the job; testing against one database and running against another; retry logic replaying completion for an already-processed job 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/23be49103a30bcf7. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/cmd/AbstractExternalWorkerJobCmd.java:70

    }

    protected abstract void runJobLogic(ExternalWorkerJobEntity externalWorkerJob, CommandContext commandContext);

    protected ExternalWorkerJobEntity resolveJob() {
        if (StringUtils.isEmpty(externalJobId)) {
            throw new FlowableIllegalArgumentException("externalJobId must not be empty");
        }

        if (StringUtils.isEmpty(workerId)) {
            throw new FlowableIllegalArgumentException("workerId must not be empty");
        }

        ExternalWorkerJobEntityManager externalWorkerJobEntityManager = jobServiceConfiguration.getExternalWorkerJobEntityManager();

        ExternalWorkerJobEntity job = externalWorkerJobEntityManager.findById(externalJobId);

        if (job == null) {
            throw new FlowableObjectNotFoundException("No External Worker job found for id: " + externalJobId, ExternalWorkerJobEntity.class);
        }

        if (!Objects.equals(workerId, job.getLockOwner())) {
            throw new FlowableIllegalArgumentException(workerId + " does not hold a lock on the requested job");
        }

        return job;
    }
}

View on GitHub (pinned to d6d39ce1c6)