flowable/flowable-engine · error · FlowableObjectNotFoundException

No external worker job found with id '

Error message

No external worker job found with id '

What it means

DeleteExternalWorkerJobCmd loads the external worker job via ExternalWorkerJobEntityManager.findById and throws FlowableObjectNotFoundException when no entity matches the given id. The referenced row does not exist in the external worker job table at deletion time.

Solutions

  1. Look up the job first via the external worker job query (managementService.getExternalWorkerJobs or ExternalWorkerJobQueryBuilder) and only delete when found.
  2. Treat FlowableObjectNotFoundException as success (idempotent delete) in code that runs cancellation concurrently.
  3. Confirm the id is an external worker job id, not a timer/message/suspended job id — different tables hold different job kinds.
  4. Verify both the worker and the engine point at the same database/schema and tenant.

Example fix

// before
managementService.executeCommand(new DeleteExternalWorkerJobCmd(externalJobId));
// after
if (managementService.createExternalWorkerJobQueryBuilder().externalWorkerJobId(externalJobId).count() > 0) {
    managementService.executeCommand(new DeleteExternalWorkerJobCmd(externalJobId));
}
Defensive patterns

Strategy: try-catch

Validate before calling

long count = managementService.createExternalWorkerJobQueryBuilder()
        .externalWorkerJobId(externalJobId).count();
if (count == 0) { LOGGER.info("External worker job {} not found; skipping", externalJobId); return; }

Try / catch

try {
    managementService.executeCommand(new DeleteExternalWorkerJobCmd(externalJobId));
} catch (FlowableObjectNotFoundException e) {
    LOGGER.info("External worker job {} already removed", externalJobId);
}

Prevention

When it happens

Trigger: Deleting an external worker job whose id was already consumed (e.g. after acquireAndLock/complete/bpmnError removed it), an id belonging to another job type (regular timer/message job instead of external worker job), or a fabricated/typo id.

Common situations: External worker job completed concurrently by another worker or lock expired and the job was recycled; cancel paths in tests running twice; querying ACT_RU_EXT_JOB ids through the wrong management API; multi-engine setups where the id exists in a different engine's database.

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/8695e29a5ed29abc. Report an issue: GitHub.

Appendix: source

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

    protected String jobId;
    protected JobServiceConfiguration jobServiceConfiguration;

    public DeleteExternalWorkerJobCmd(String jobId, JobServiceConfiguration jobServiceConfiguration) {
        this.jobId = jobId;
        this.jobServiceConfiguration = jobServiceConfiguration;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        if (jobId == null) {
            throw new FlowableIllegalArgumentException("jobId is null");
        }

        ExternalWorkerJobEntityManager jobEntityManager = jobServiceConfiguration.getExternalWorkerJobEntityManager();

        ExternalWorkerJobEntity job = jobEntityManager.findById(jobId);
        if (job == null) {
            throw new FlowableObjectNotFoundException("No external worker job found with id '" + jobId + "'", Job.class);
        }

        FlowableEventDispatcher eventDispatcher = jobServiceConfiguration.getEventDispatcher();
        if (eventDispatcher != null && eventDispatcher.isEnabled()) {
            eventDispatcher.dispatchEvent(FlowableJobEventBuilder.createEntityEvent(FlowableEngineEventType.JOB_CANCELED, job),
                    jobServiceConfiguration.getEngineName());
        }

        jobEntityManager.delete(job);

        return null;
    }
}

View on GitHub (pinned to d6d39ce1c6)