flowable/flowable-engine · error · FlowableException
Task ${taskId} is not suspended, so can't be activated
Error message
Task ${taskId} is not suspended, so can't be activated What it means
Flowable CMMN throws this when ActivateTaskCmd is executed against a plan item / task whose entity is not currently suspended. Activation (clearing suspendedTime/suspendedBy) is only meaningful for suspended tasks, so the command fails fast with a FlowableException to prevent an invalid state transition.
Source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/cmd/ActivateTaskCmd.java:62
public Void execute(CommandContext commandContext) {
CmmnEngineConfiguration cmmnEngineConfiguration = CommandContextUtil.getCmmnEngineConfiguration(commandContext);
if (taskId == null) {
throw new FlowableIllegalArgumentException("taskId is null");
}
TaskEntity task = cmmnEngineConfiguration.getTaskServiceConfiguration().getTaskService().getTask(taskId);
if (task == null) {
throw new FlowableObjectNotFoundException("Cannot find task with id " + taskId, Task.class);
}
if (task.isDeleted()) {
throw new FlowableException("Task " + taskId + " is already deleted");
}
if (!task.isSuspended()) {
throw new FlowableException("Task " + taskId + " is not suspended, so can't be activated");
}
Clock clock = cmmnEngineConfiguration.getClock();
Date updateTime = clock.getCurrentTime();
task.setSuspendedTime(null);
task.setSuspendedBy(null);
if (task.getInProgressStartTime() != null) {
task.setState(Task.IN_PROGRESS);
} else if (task.getClaimTime() != null) {
task.setState(Task.CLAIMED);
} else {
task.setState(Task.CREATED);
}
task.setSuspensionState(SuspensionState.ACTIVE.getStateCode());
List<PlanItemInstanceEntity> planItemInstances = cmmnEngineConfiguration.getPlanItemInstanceEntityManager().findByReferenceId(task.getId());
if (planItemInstances != null && !planItemInstances.isEmpty()) {View on GitHub (pinned to d6d39ce1c6)
Solutions
- Check task.isSuspended() (via TaskService.createTaskQuery().taskId(id).singleResult()) before calling activateTask
- Skip or log tasks already active instead of activating unconditionally
- Serialize activation calls (idempotent handling) so concurrent callers don't double-activate
- Verify the correct taskId was passed — a wrong/stale id may point at a never-suspended task
Example fix
// before
taskService.activateTask(taskId);
// after
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
if (task != null && task.isSuspended()) {
taskService.activateTask(taskId);
} Defensive patterns
Strategy: validation
Validate before calling
Task t = cmmnTaskService.createTaskQuery().taskId(taskId).singleResult();
if (t == null) throw new IllegalArgumentException("task not found: " + taskId);
boolean canActivate = t.isSuspended(); Type guard
boolean canActivate(Task t) { return t != null && t.isSuspended(); } Try / catch
try {
cmmnTaskService.activateTask(taskId);
} catch (FlowableException e) {
if (e.getMessage().contains("not suspended")) { /* already active: skip/log */ }
else throw e;
} Prevention
- Query isSuspended() before activating
- Make activation idempotent — treat 'not suspended' as a no-op in retries
- Avoid activating whole batches blindly; filter by suspended state in the task query
- Guard against concurrent activation with locking or single writer
When it happens
Trigger: Calling CmmnTaskService.activateTask(taskId) (or the ActivateTaskCmd directly) on a task whose TaskEntity.isSuspended() is false — e.g. the task was never suspended, or it was already activated in a prior call.
Common situations: Double-invocation of activation after a retry, activating tasks in bulk where only some are suspended, race between two threads/instances where one already activated the task, or confusing suspend with other state changes like completion.
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
- Cannot exit stage with 'complete' event type as the stage '{
- plan item instance can only be resumed if the state is suspe
- plan item instance is already suspended
- Cannot exit case with 'complete' event type as the case '${c
- Can only trigger an event listener plan item that is in the
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/80b805590a70e5bc.
Report an issue: GitHub.