{"record":{"id":"25808cf94f963afd","repo":"conductor-oss/conductor","slug":"workflow-id-s-already-belongs-to-parent-workflow","errorCode":null,"errorMessage":"Workflow id %s already belongs to parent workflow %s task %s, cannot attach to parent workflow %s task %s","messagePattern":"Workflow id (.+?) already belongs to parent workflow (.+?) task (.+?), cannot attach to parent workflow (.+?) task (.+?)","errorType":"exception","errorClass":"NonTransientException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/com/netflix/conductor/core/execution/WorkflowExecutorOps.java","lineNumber":2702,"sourceCode":"            StartWorkflowInput input, WorkflowModel existingWorkflow) {\n        if (StringUtils.isBlank(input.getParentWorkflowId())\n                && StringUtils.isBlank(input.getParentWorkflowTaskId())) {\n            return;\n        }\n\n        if (!StringUtils.equals(input.getParentWorkflowId(), existingWorkflow.getParentWorkflowId())\n                || !StringUtils.equals(\n                        input.getParentWorkflowTaskId(),\n                        existingWorkflow.getParentWorkflowTaskId())) {\n            String message =\n                    String.format(\n                            \"Workflow id %s already belongs to parent workflow %s task %s, cannot attach to parent workflow %s task %s\",\n                            existingWorkflow.getWorkflowId(),\n                            existingWorkflow.getParentWorkflowId(),\n                            existingWorkflow.getParentWorkflowTaskId(),\n                            input.getParentWorkflowId(),\n                            input.getParentWorkflowTaskId());\n            throw new NonTransientException(message);\n        }\n    }\n\n    private void createAndEvaluate(WorkflowModel workflow) {\n        if (!executionLockService.acquireLock(workflow.getWorkflowId())) {\n            throw new TransientException(\"Error acquiring lock when creating workflow: {}\");\n        }\n        try {\n            createAndEvaluateWithLock(workflow);\n        } finally {\n            executionLockService.releaseLock(workflow.getWorkflowId());\n        }\n    }\n\n    private void createAndEvaluateWithLock(WorkflowModel workflow) {\n        executionDAOFacade.createWorkflow(workflow);\n        LOGGER.debug(\n                \"A new instance of workflow: {} created with id: {}\",","sourceCodeStart":2684,"sourceCodeEnd":2720,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/core/src/main/java/com/netflix/conductor/core/execution/WorkflowExecutorOps.java#L2684-L2720","documentation":"Thrown by validateIdempotentWorkflowOwnership() during startWorkflowIdempotent. When a workflow with the given ID already exists, Conductor verifies that the requested parentWorkflowId/parentWorkflowTaskId match the stored values. A mismatch means you are trying to attach an existing workflow to a different parent — which would corrupt the parent-child execution graph. This is a NonTransientException: no retry will change the outcome.","triggerScenarios":"Calling startWorkflowIdempotent with workflowId X and parentWorkflowId P2, but workflow X was originally created as a child of parent P1. The existing workflow's parentWorkflowId or parentWorkflowTaskId does not equal the ones in the current request.","commonSituations":"Two different parent workflows both supplying the same hardcoded workflowId for their children. A bug in the sub-workflow task that generates duplicate workflow IDs. Attempting to 'reparent' a workflow by re-issuing an idempotent start with different parent parameters.","solutions":["Use a unique workflowId per idempotent start — do not reuse IDs across different parent contexts.","If the existing workflow is stale, remove it (DELETE /api/workflow/{workflowId}) and retry the idempotent start.","Verify that the parentWorkflowId and parentWorkflowTaskId passed in StartWorkflowInput match those of the original creation.","Audit your SubWorkflow task implementation to ensure it generates unique, parent-scoped workflow IDs."],"exampleFix":"// before\nStartWorkflowInput input = StartWorkflowInput.builder()\n    .workflowId(\"my-fixed-id\")\n    .parentWorkflowId(newParentId)\n    .parentWorkflowTaskId(newParentTaskId)\n    .build();\nworkflowExecutor.startWorkflowIdempotent(input);\n\n// after\nString wfId = UUID.randomUUID().toString(); // unique per start\nStartWorkflowInput input = StartWorkflowInput.builder()\n    .workflowId(wfId)\n    .parentWorkflowId(newParentId)\n    .parentWorkflowTaskId(newParentTaskId)\n    .build();\nworkflowExecutor.startWorkflowIdempotent(input);","handlingStrategy":"validation","validationCode":"// Before idempotent start with a parent, check if workflow exists\nWorkflowModel existing = null;\ntry {\n    existing = executionDAOFacade.getWorkflowModelFromExecutionDAO(workflowId, false);\n} catch (NotFoundException ignored) {}\nif (existing != null) {\n    if (!StringUtils.equals(input.getParentWorkflowId(), existing.getParentWorkflowId())\n            || !StringUtils.equals(input.getParentWorkflowTaskId(), existing.getParentWorkflowTaskId())) {\n        throw new IllegalStateException(\"Workflow already attached to a different parent\");\n    }\n}\nworkflowExecutor.startWorkflowIdempotent(input);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Generate unique workflowIds per idempotent start — never reuse across parents.","If reusing IDs, verify parent parameters match the existing workflow before calling start.","Audit SubWorkflow task implementations to ensure they generate parent-scoped unique IDs."],"tags":["idempotent-start","parent-workflow","non-transient","ownership"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}