{"record":{"id":"c601d7c99be59fc3","repo":"eyaltoledano/claude-task-master","slug":"cannot-create-circular-dependency-task-parentid","errorCode":null,"errorMessage":"Cannot create circular dependency: task ${parentIdNum} is already a subtask or dependent of task ${existingTaskIdNum}","messagePattern":"Cannot create circular dependency: task (.+?) is already a subtask or dependent of task (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/modules/task-manager/add-subtask.js","lineNumber":79,"sourceCode":"\n\t\t\tconst existingTask = data.tasks[existingTaskIndex];\n\n\t\t\t// Check if task is already a subtask\n\t\t\tif (existingTask.parentTaskId) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Task ${existingTaskIdNum} is already a subtask of task ${existingTask.parentTaskId}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Check for circular dependency\n\t\t\tif (existingTaskIdNum === parentIdNum) {\n\t\t\t\tthrow new Error(`Cannot make a task a subtask of itself`);\n\t\t\t}\n\n\t\t\t// Check if parent task is a subtask of the task we're converting\n\t\t\t// This would create a circular dependency\n\t\t\tif (isTaskDependentOn(data.tasks, parentTask, existingTaskIdNum)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot create circular dependency: task ${parentIdNum} is already a subtask or dependent of task ${existingTaskIdNum}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Find the highest subtask ID to determine the next ID\n\t\t\tconst highestSubtaskId =\n\t\t\t\tparentTask.subtasks.length > 0\n\t\t\t\t\t? Math.max(...parentTask.subtasks.map((st) => st.id))\n\t\t\t\t\t: 0;\n\t\t\tconst newSubtaskId = highestSubtaskId + 1;\n\n\t\t\t// Clone the existing task to be converted to a subtask\n\t\t\tnewSubtask = {\n\t\t\t\t...existingTask,\n\t\t\t\tid: newSubtaskId,\n\t\t\t\tparentTaskId: parentIdNum\n\t\t\t};\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/scripts/modules/task-manager/add-subtask.js#L61-L97","documentation":"addSubtask uses isTaskDependentOn to detect whether attaching the existing task under the parent would create a cycle: if the parent is already a subtask of, or depends on, the task being converted, the hierarchy would become circular. The error names both IDs to help untangle the dependency graph.","triggerScenarios":"Calling addSubtask(parentId, existingTaskId) where parentId is a subtask/dependent of existingTaskId — e.g. converting task A into a subtask of task B when B already depends on A.","commonSituations":"Complex dependency graphs built up over time, scripting batch conversions without cycle analysis, or users reorganizing tasks without visualizing dependencies.","solutions":["Inspect the dependency graph of both tasks (task-master shows dependencies) to find the cycle.","Remove the offending dependency or subtask relationship first, then retry the conversion.","Choose a different parent task that does not depend on the candidate child.","Restructure so the hierarchy is acyclic (e.g. convert the parent instead)."],"exampleFix":"// before\nawait addSubtask('2', '1'); // task 2 depends on task 1 → cycle\n// after\n// remove task 2's dependency on task 1 first, then:\nawait addSubtask('2', '1');","handlingStrategy":"validation","validationCode":"const data = readJSON(tasksPath, projectRoot, tag);\nconst parent = data.tasks.find(t => t.id === parseInt(parentId, 10));\nconst child = data.tasks.find(t => t.id === parseInt(existingTaskId, 10));\nif (parent && child && isTaskDependentOn(data.tasks, parent, child.id)) {\n  throw new Error(`Cycle: task ${parent.id} already depends on task ${child.id}`);\n}","typeGuard":"function createsCycle(parent, childId, deps = parent?.dependencies || []) {\n  return deps.includes(childId) || parent?.parentTaskId === childId;\n}","tryCatchPattern":"try {\n  await addSubtask(tasksPath, parentId, existingTaskId);\n} catch (err) {\n  if (err.message.startsWith('Cannot create circular dependency')) {\n    // remove the offending dependency or pick a different parent\n  } else throw err;\n}","preventionTips":["Visualize the dependency graph before restructuring hierarchies","Run cycle-detection checks in scripts that batch-convert tasks","Keep dependencies shallow; deep chains invite cycles","Add CI checks that reject cyclic task graphs"],"tags":["tasks","circular-dependency","dependencies","graph"],"backgroundTag":"circular-dependency","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}