flowable/flowable-engine · error · FlowableIllegalArgumentException

Can not activate job ${jobId}. Parent is suspended.

Error message

Can not activate job ${jobId}. Parent is suspended.

What it means

Flowable suspends process definitions/instances hierarchically: a job whose parent (process instance, process definition, or deployment) is suspended cannot be individually activated. JobServiceImpl.activateSuspendedJob() consults the JobParentStateResolver and throws FlowableIllegalArgumentException if the job's parent is still suspended, preventing an inconsistent state where an active job belongs to a suspended parent.

Source

Thrown at modules/flowable-job-service/src/main/java/org/flowable/job/service/impl/JobServiceImpl.java:130

    }
    
    @Override
    public List<DeadLetterJobEntity> findDeadLetterJobsByProcessInstanceId(String processInstanceId) {
        return getDeadLetterJobEntityManager().findJobsByProcessInstanceId(processInstanceId);
    }
    
    @Override
    public void updateAllJobTypesTenantIdForDeployment(String deploymentId, String newTenantId) {
        getJobEntityManager().updateJobTenantIdForDeployment(deploymentId, newTenantId);
        getTimerJobEntityManager().updateJobTenantIdForDeployment(deploymentId, newTenantId);
        getSuspendedJobEntityManager().updateJobTenantIdForDeployment(deploymentId, newTenantId);
        getDeadLetterJobEntityManager().updateJobTenantIdForDeployment(deploymentId, newTenantId);
    }
    
    @Override
    public AbstractRuntimeJobEntity activateSuspendedJob(SuspendedJobEntity job) {
        if (configuration.getJobParentStateResolver().isSuspended(job)) {
            throw new FlowableIllegalArgumentException("Can not activate job "+ job.getId() +". Parent is suspended.");
        }
        return getJobManager().activateSuspendedJob(job);
    }

    @Override
    public SuspendedJobEntity moveJobToSuspendedJob(AbstractRuntimeJobEntity job) {
        return getJobManager().moveJobToSuspendedJob(job);
    }

    @Override
    public AbstractRuntimeJobEntity moveJobToDeadLetterJob(AbstractRuntimeJobEntity job) {
        return getJobManager().moveJobToDeadLetterJob(job);
    }

    @Override
    public JobEntity createJob() {
        return getJobEntityManager().create();
    }

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Activate the parent first: call managementService.activateProcessInstanceById(pid) or activateProcessDefinitionById(id) before activating the job
  2. Lift the suspension at the level it was applied (process definition or deployment) using the matching activate* command
  3. If per-job activation is intended, ensure the parent was never suspended or has already been re-activated, then retry

Example fix

// before
managementService.activateJob(jobId); // parent still suspended -> error
// after
managementService.activateProcessInstanceById(processInstanceId);
managementService.activateJob(jobId);
Defensive patterns

Strategy: try-catch

Validate before calling

// Check parent state before activating
boolean suspended = managementService.createProcessInstanceQuery()
    .processInstanceId(pid)
    .suspended()
    .count() > 0;
if (suspended) {
    managementService.activateProcessInstanceById(pid);
}

Try / catch

try {
    managementService.activateJob(jobId);
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage() != null && e.getMessage().contains("Parent is suspended")) {
        // activate parent, then retry once
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling managementService.activateJob(jobId) (or activateJobByProcessInstanceId etc.) for a job whose owning process instance or process definition is currently suspended; trying to activate a job while its deployment-level suspension is still in effect.

Common situations: Administrators resuming a single job after a suspendAll() without first lifting the suspension on the parent process instance/definition; scripted recovery jobs that activate jobs while the whole deployment remains suspended; race conditions where suspension and activation happen concurrently.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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