flowable/flowable-engine · error · ActivitiException
Cannot set suspension state for execution '${executionId}':
Error message
Cannot set suspension state for execution '${executionId}': not a process instance. What it means
AbstractSetProcessInstanceStateCmd.execute requires the found execution to actually be a process instance (root execution). If the id resolves to a child/concurrent execution, changing the process instance suspension state on it is rejected with an ActivitiException.
Source
Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cmd/AbstractSetProcessInstanceStateCmd.java:57
public AbstractSetProcessInstanceStateCmd(String executionId) {
this.executionId = executionId;
}
@Override
public Void execute(CommandContext commandContext) {
if (executionId == null) {
throw new ActivitiIllegalArgumentException("ProcessInstanceId cannot be null.");
}
ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findExecutionById(executionId);
if (executionEntity == null) {
throw new ActivitiObjectNotFoundException("Cannot find processInstance for id '" + executionId + "'.", Execution.class);
}
if (!executionEntity.isProcessInstanceType()) {
throw new ActivitiException("Cannot set suspension state for execution '" + executionId + "': not a process instance.");
}
SuspensionStateUtil.setSuspensionState(executionEntity, getNewState());
// All child executions are suspended
List<ExecutionEntity> childExecutions = commandContext.getExecutionEntityManager().findChildExecutionsByProcessInstanceId(executionId);
for (ExecutionEntity childExecution : childExecutions) {
if (!childExecution.getId().equals(executionId)) {
SuspensionStateUtil.setSuspensionState(childExecution, getNewState());
}
}
// All tasks are suspended
List<TaskEntity> tasks = commandContext.getTaskEntityManager().findTasksByProcessInstanceId(executionId);
for (TaskEntity taskEntity : tasks) {
SuspensionStateUtil.setSuspensionState(taskEntity, getNewState());
}
View on GitHub (pinned to d6d39ce1c6)
Solutions
- Use the processInstanceId: for any execution, executionEntity.getProcessInstanceId() gives the root id to pass to this API.
- If you have an Execution object, pass execution.getProcessInstanceId() instead of execution.getId().
- Verify with runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult() that the id denotes a process instance.
Example fix
// before runtimeService.suspendProcessInstanceById(execution.getId()); // after runtimeService.suspendProcessInstanceById(execution.getProcessInstanceId());
Defensive patterns
Strategy: type-guard
Validate before calling
ExecutionEntity e = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(id).singleResult();
if (e == null || !e.isProcessInstanceType()) { throw new IllegalStateException("id is not a process instance"); } Type guard
boolean isProcessInstance(Execution execution) {
return execution instanceof ProcessInstance;
} Try / catch
try {
runtimeService.suspendProcessInstanceById(id);
} catch (ActivitiException e) {
if (e.getMessage() != null && e.getMessage().contains("not a process instance")) {
String rootId = runtimeService.createExecutionQuery().executionId(id).singleResult().getProcessInstanceId();
runtimeService.suspendProcessInstanceById(rootId);
} else { throw e; }
} Prevention
- Use execution.getProcessInstanceId() for instance-level APIs
- Narrow execution query results with .processInstanceId filter
- Cast-check with instanceof ProcessInstance before instance-level calls
When it happens
Trigger: Calling suspendProcessInstanceById/activateProcessInstanceById with the id of a child execution or concurrent execution (ExecutionEntity from an execution query / execution listener context) rather than the process instance id.
Common situations: Storing Execution.getId() from an intermediate activity instead of the process instance id; iterating executions from createExecutionQuery() and passing every id to the process-instance-level API.
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 find processInstance for id '${executionId}'.
- processInstanceId is null
- No process instance found for id '${processInstanceId}'
- Process instance id is null
- Set of process instance ids is null
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/7cc8e8715b5fdb07.
Report an issue: GitHub.