{"record":{"id":"67eed4d89ca517c8","repo":"flowable/flowable-engine","slug":"error-while-completing-sub-process-of-execution","errorCode":null,"errorMessage":"Error while completing sub process of execution ${processInstanceExecution}","messagePattern":"Error while completing sub process of execution (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/EndExecutionOperation.java","lineNumber":111,"sourceCode":"        ExecutionEntity superExecution = processInstanceExecution.getSuperExecution();\n        if (!forceSynchronous && isAsyncCompleteCallActivity(superExecution)) {\n            scheduleAsyncCompleteCallActivity(superExecution, processInstanceExecution);\n            return;\n        }\n        \n        // copy variables before destroying the ended sub process instance (call activity)\n        SubProcessActivityBehavior subProcessActivityBehavior = null;\n        if (superExecution != null) {\n            FlowNode superExecutionElement = (FlowNode) superExecution.getCurrentFlowElement();\n            subProcessActivityBehavior = (SubProcessActivityBehavior) superExecutionElement.getBehavior();\n            try {\n                subProcessActivityBehavior.completing(superExecution, processInstanceExecution);\n            } catch (RuntimeException e) {\n                LOGGER.error(\"Error while completing sub process of execution {}\", processInstanceExecution, e);\n                throw e;\n            } catch (Exception e) {\n                LOGGER.error(\"Error while completing sub process of execution {}\", processInstanceExecution, e);\n                throw new FlowableException(\"Error while completing sub process of execution \" + processInstanceExecution, e);\n            }\n        }\n\n        int activeExecutions = getNumberOfActiveChildExecutionsForProcessInstance(executionEntityManager, processInstanceId);\n        if (activeExecutions == 0) {\n            LOGGER.debug(\"No active executions found. Ending process instance {}\", processInstanceId);\n\n            // note the use of execution here vs processinstance execution for getting the flow element\n            executionEntityManager.deleteProcessInstanceExecutionEntity(processInstanceId,\n                    execution.getCurrentFlowElement() != null ? execution.getCurrentFlowElement().getId() : null, null, false, false, true);\n        } else {\n            LOGGER.debug(\"Active executions found. Process instance {} will not be ended.\", processInstanceId);\n        }\n\n        Process process = ProcessDefinitionUtil.getProcess(processInstanceExecution.getProcessDefinitionId());\n\n        // Execute execution listeners for process end.\n        if (CollectionUtil.isNotEmpty(process.getExecutionListeners())) {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable-engine/src/main/java/org/flowable/engine/impl/agenda/EndExecutionOperation.java#L93-L129","documentation":"When a process-instance-level execution ends inside a call activity's child, EndExecutionOperation notifies the parent's SubProcessActivityBehavior.completing(...). Any Exception (checked) thrown by that behavior is wrapped in this FlowableException; RuntimeExceptions rethrown keep their type. The message is a wrapper — the cause holds the real error.","triggerScenarios":"The child process instance's execution ends while the call activity's behavior (completing phase) throws a checked Exception in the super execution.","commonSituations":"Custom ActivityBehavior implementations in the parent process throwing checked exceptions; delegation to business logic that fails (IO, service calls) during sub-process completion.","solutions":["Inspect the cause chain of this FlowableException for the underlying exception","Fix the failing ActivityBehavior or wrap its logic to convert/handle checked exceptions","Add error boundary events / job retries if the failing work is external"],"exampleFix":"// before (custom behavior)\npublic void completing(DelegateExecution superExecution, DelegateExecution subProcessExecution) throws Exception {\n    externalClient.notifyDone(); // throws checked IOException\n}\n// after\npublic void completing(DelegateExecution superExecution, DelegateExecution subProcessExecution) {\n    try {\n        externalClient.notifyDone();\n    } catch (IOException e) {\n        throw new RuntimeException(\"Sub-process completion callback failed\", e);\n    }\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    // operation ending the sub-process execution\n} catch (FlowableException e) {\n    log.error(\"Sub-process completing failed, cause: {}\", e.getCause(), e.getCause());\n    throw e;\n}","preventionTips":["Always inspect the cause chain on this wrapper exception","Avoid checked exceptions in custom ActivityBehaviors","Make external calls in behaviors async/retriable","Log inside custom behaviors with execution context"],"tags":["java","flowable","call-activity","subprocess"],"backgroundTag":"internal-invariant-violation","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}