eyaltoledano/claude-task-master · error · MoveTaskError
TASK_ALREADY_EXISTS
TASK_ALREADY_EXISTS
Error message
Cannot move to existing task ID ${destTaskId}. Choose a different ID or use subtask destination. What it means
This MoveTaskError with code TASK_ALREADY_EXISTS is thrown when moving a subtask out to become a standalone task, but the destination task ID is already occupied in the task list. The library refuses to overwrite or swap tasks implicitly during a subtask-to-task move, because doing so would silently destroy an existing task's data. It suggests either picking a free ID or, alternatively, moving the subtask to a different parent as a subtask destination.
Source
Thrown at scripts/modules/task-manager/move-task.js:339
}
// Find source subtask
const sourceSubtaskIndex = sourceParentTask.subtasks.findIndex(
(st) => st.id === sourceSubtaskId
);
if (sourceSubtaskIndex === -1) {
throw new MoveTaskError(
MOVE_ERROR_CODES.SUBTASK_NOT_FOUND,
`Source subtask ${sourceId} not found`
);
}
const sourceSubtask = sourceParentTask.subtasks[sourceSubtaskIndex];
// Check if destination task exists
const existingDestTask = tasks.find((t) => t.id === destTaskId);
if (existingDestTask) {
throw new MoveTaskError(
MOVE_ERROR_CODES.TASK_ALREADY_EXISTS,
`Cannot move to existing task ID ${destTaskId}. Choose a different ID or use subtask destination.`
);
}
// Create new task from subtask
const newTask = {
id: destTaskId,
title: sourceSubtask.title,
description: sourceSubtask.description,
status: sourceSubtask.status || 'pending',
dependencies: sourceSubtask.dependencies || [],
priority: sourceSubtask.priority || 'medium',
details: sourceSubtask.details || '',
testStrategy: sourceSubtask.testStrategy || '',
subtasks: []
};
View on GitHub (pinned to c0c98d367c)
Solutions
- Pick a destination ID that does not exist: run `tasks.some(t => t.id === destId)` first and choose the next free ID.
- If the goal is to keep it nested, pass a subtask destination (parent.subsubtask form) instead of a task ID.
- List current tasks to find free IDs, then retry the move with a valid one.
- If overwriting is truly intended, delete or move the existing task at that ID first, then retry.
- If rerunning a migration, make it idempotent by skipping when the destination already exists.
Example fix
// before moveTask(tasksPath, '5.2', '3'); // task 3 exists -> TASK_ALREADY_EXISTS // after const tasks = readJSON(tasksPath); const nextId = Math.max(...tasks.map(t => t.id)) + 1; moveTask(tasksPath, '5.2', String(nextId));
Defensive patterns
Strategy: validation
Validate before calling
const tasks = JSON.parse(fs.readFileSync(tasksPath, 'utf8')).master.tasks;
if (tasks.some(t => t.id === Number(destTaskId))) {
throw new Error(`Destination ID ${destTaskId} is taken; pick a free ID.`);
} Type guard
function isFreeTaskId(tasks, id) {
return Number.isInteger(id) && !tasks.some(t => t.id === id);
} Try / catch
try {
await moveTask(tasksPath, '5.2', destId);
} catch (e) {
if (e.code === 'TASK_ALREADY_EXISTS') {
const freeId = Math.max(...getTasks().map(t => t.id)) + 1;
await moveTask(tasksPath, '5.2', String(freeId));
} else throw e;
} Prevention
- Always compute destination IDs as max(existing)+1 and verify with tasks.some() before moving.
- Never hardcode destination task IDs in scripts.
- Re-read tasks.json immediately before each move to avoid stale data.
- Avoid concurrent move operations against the same tasks.json.
- For nested moves, use subtask destinations instead of claiming a top-level ID.
When it happens
Trigger: Calling moveTask (or moveTaskToTask via moveTask) with a source that is a subtask (sourceId like '5.2') and a numeric destination ID that already exists in tasks, e.g. moving subtask 5.2 to task ID 3 when task 3 exists.
Common situations: Auto-picking the destination ID from user input without checking availability; scripts that compute a target ID as max(existing)+1 but run on stale task data; running two move operations concurrently; rerunning a migration script that already created the destination task on a previous run.
Related errors
- TASK_NOT_FOUND
- INVALID_SOURCE_TAG
- CROSS_TAG_DEPENDENCY_CONFLICTS
- Task description is required
- Task status is required
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/ca3fb868aecf25ea.
Report an issue: GitHub.