flowable/flowable-engine · error · FlowableObjectNotFoundException

No External Worker job found for id

Error message

No External Worker job found for id: {externalJobId}

What it means

After loading the job by id, resolveJob throws FlowableObjectNotFoundException (with ExternalWorkerJobEntity.class as the entity type) when the job row does not exist. The command cannot proceed because the referenced external worker job is gone or was never created with that id.

Solutions

  1. Catch FlowableObjectNotFoundException in the worker and treat the job as already handled (skip/retry acquisition).
  2. Re-acquire fresh jobs instead of retrying stale job ids from a local cache.
  3. Verify the id and that the command runs against the same engine/database/tenant where the job was acquired.

Example fix

// before
jobService.complete(jobId, workerId, variables); // throws if job gone
// after
try {
    jobService.complete(jobId, workerId, variables);
} catch (FlowableObjectNotFoundException e) {
    log.info("Job {} already gone, skipping", jobId);
}
Defensive patterns

Strategy: try-catch

Validate before calling

ExternalWorkerJob job = jobService.createExternalWorkerJobQuery().externalJobId(jobId).singleResult(); // check before acting

Try / catch

try {
    jobService.complete(jobId, workerId, variables);
} catch (FlowableObjectNotFoundException e) {
    // job already completed/expired: skip and re-acquire
}

Prevention

When it happens

Trigger: Calling complete/fail/release with an externalJobId that no longer exists: job already completed and deleted, expired/failed job removed by job cleaner, id typo, or querying against a different database/tenant.

Common situations: Two workers raced and one finished the job first; long retries after the job expired (lock expired and job deleted); stale job id cached on the worker side; cross-environment id reuse.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/cmd/AbstractExternalWorkerJobCmd.java:87

        processEngineConfiguration.getIdentityLinkServiceConfiguration().getIdentityLinkService()
                .deleteIdentityLinksByScopeIdAndType(externalWorkerJob.getCorrelationId(), ScopeTypes.EXTERNAL_WORKER);
    }

    protected ExternalWorkerJobEntity resolveJob(CommandContext commandContext) {
        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)