flowable/flowable-engine · error · FlowableException

Execution has no parent execution " +…

Error message

Execution has no parent execution " + execution.getParentId()

What it means

During doMoveExecutionState, before moving, the code ensures it is not operating on the root execution: a null parentId means the execution is the process-instance root and cannot be deleted/re-parented as part of the move. The message is misleading — it always interpolates null since it fires only when getParentId() == null.

Solutions

  1. Ensure the source activity ids map to leaf/concurrent executions, not the root process instance execution
  2. Check that filtered executions exclude the process-instance-type execution before building the move container
  3. If implementing a custom dynamic state manager, exclude root executions from the move set

Example fix

// before
List<ExecutionEntity> toMove = executions;
// after
List<ExecutionEntity> toMove = executions.stream().filter(e -> e.getParentId() != null).collect(toList());
Defensive patterns

Strategy: validation

Validate before calling

if (execution.isProcessInstanceType() || execution.getParentId() == null) throw new IllegalStateException("Root execution cannot be moved");

Type guard

boolean isMovable(ExecutionEntity e) { return e.getParentId() != null; }

Try / catch

try { builder.changeState(); } catch (FlowableException e) { if (e.getMessage().startsWith("Execution has no parent")) { /* exclude root execution from move set */ } else throw e; }

Prevention

When it happens

Trigger: A move/change-state operation resolving to the root process-instance execution as one of the executions to move (e.g. source activity id accidentally matches the process instance scope, or move container resolved the root execution).

Common situations: Passing the process instance's own scope id as an activity id; move containers built from executions lacking currentActivityId filtering; custom subclasses of AbstractDynamicStateManager feeding wrong executions.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java:555

                                                executionEntity.setProcessDefinitionId(processInstanceChangeState.getProcessDefinitionToMigrateTo().getId());
                                                childExecutionsToKeep.add(executionEntity.getId());
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }

                executionEntityManager.deleteChildExecutions(execution, childExecutionsToKeep, null, "Change parent activity to " + flowElementIdsLine, true, null);
                if (!moveExecutionContainer.isDirectExecutionMigration()) {
                    executionEntityManager.deleteExecutionAndRelatedData(execution, "Change activity to " + flowElementIdsLine, false, false, true, execution.getCurrentFlowElement());
                }

                // Make sure we are not moving the root execution
                if (execution.getParentId() == null) {
                    throw new FlowableException("Execution has no parent execution " + execution.getParentId());
                }

                // Delete the parent executions for each current execution when the move to activity id has the same subProcess scope
                ExecutionEntity continueParentExecution;
                if (processInstanceChangeState.getProcessDefinitionToMigrateTo() != null) {
                    continueParentExecution = deleteDirectParentExecutions(execution.getParentId(), moveToFlowElements, 
                    		executionIdsNotToDelete, processInstanceChangeState.getProcessDefinitionToMigrateTo(), moveExecutionContainer, commandContext);
                } else {
                    continueParentExecution = deleteParentExecutions(execution.getParentId(), moveToFlowElements, executionIdsNotToDelete, commandContext);
                }
                moveExecutionContainer.addContinueParentExecution(execution.getId(), continueParentExecution);
            }

            List<ExecutionEntity> newChildExecutions = createEmbeddedSubProcessAndExecutions(moveToFlowElements, executionsToMove, moveExecutionContainer, processInstanceChangeState, commandContext);

            if (moveExecutionContainer.isMoveToSubProcessInstance()) {
                CallActivity callActivity = moveExecutionContainer.getCallActivity();
                Process subProcess = moveExecutionContainer.getSubProcessModel().getProcessById(moveExecutionContainer.getSubProcessDefKey());

View on GitHub (pinned to d6d39ce1c6)