flowable/flowable-engine · error · FlowableObjectNotFoundException

No suspended job found with id '

Error message

No suspended job found with id '

What it means

DeleteSuspendedJobCmd fetches the job via SuspendedJobEntityManager.findById and throws FlowableObjectNotFoundException("No suspended job found with id '...'") with Job.class when no suspended job row matches. The id is not present in the ACT_RU_SUSPENDED_JOB table.

Solutions

  1. Re-query the suspended job table immediately before deletion and delete the current ids, not a stale snapshot.
  2. If the definition was activated, the job now lives in the regular job table — use a job query and DeleteJobCmd instead.
  3. Catch FlowableObjectNotFoundException for idempotent cleanup that may run concurrently with activation.
  4. Confirm the id's job kind and engine/database before deleting.

Example fix

// before
managementService.executeCommand(new DeleteSuspendedJobCmd(staleId));
// after
if (managementService.createSuspendedJobQuery().suspendedJobId(staleId).count() > 0) {
    managementService.executeCommand(new DeleteSuspendedJobCmd(staleId));
} else if (managementService.createJobQuery().jobId(staleId).count() > 0) {
    managementService.deleteJob(staleId); // job moved back after activation
}
Defensive patterns

Strategy: validation

Validate before calling

long count = managementService.createSuspendedJobQuery().suspendedJobId(suspendedJobId).count();
if (count == 0) {
    LOGGER.info("Suspended job {} not found; check activation state", suspendedJobId);
    return;
}

Try / catch

try {
    managementService.executeCommand(new DeleteSuspendedJobCmd(suspendedJobId));
} catch (FlowableObjectNotFoundException e) {
    LOGGER.info("Suspended job {} no longer suspended", suspendedJobId);
}

Prevention

When it happens

Trigger: Deleting a suspended job after its process definition was activated again (the job moved back to the regular job table); deleting with a regular/dead-letter job id; double deletion; typo'd id.

Common situations: Suspend/activate cycles around job cleanup: code snapshots suspended job ids, the definition is activated, then cleanup runs against stale ids; tests that suspend, delete, activate, then delete again; id confusion between job tables.

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/84e54ba210a80714. Report an issue: GitHub.

Appendix: source

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

    protected void sendCancelEvent(SuspendedJobEntity jobToDelete) {
        FlowableEventDispatcher eventDispatcher = jobServiceConfiguration.getEventDispatcher();
        if (eventDispatcher != null && eventDispatcher.isEnabled()) {
            eventDispatcher.dispatchEvent(FlowableJobEventBuilder.createEntityEvent(FlowableEngineEventType.JOB_CANCELED, jobToDelete),
                    jobServiceConfiguration.getEngineName());
        }
    }

    protected SuspendedJobEntity getJobToDelete(CommandContext commandContext) {
        if (suspendedJobId == null) {
            throw new FlowableIllegalArgumentException("jobId is null");
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Deleting job {}", suspendedJobId);
        }

        SuspendedJobEntity job = jobServiceConfiguration.getSuspendedJobEntityManager().findById(suspendedJobId);
        if (job == null) {
            throw new FlowableObjectNotFoundException("No suspended job found with id '" + suspendedJobId + "'", Job.class);
        }

        return job;
    }

}

View on GitHub (pinned to d6d39ce1c6)