eyaltoledano/claude-task-master · error · MoveTaskError

PARENT_TASK_NOT_FOUND

PARENT_TASK_NOT_FOUND

Error message

Source parent task with ID ${sourceParentId} not found

What it means

moveSubtaskToSubtask moves subtask 'X.Y' under destination 'P.Q' by locating both parent tasks (X and P) in the current tag's tasks array. If the source parent task X cannot be found, it throws MoveTaskError with code PARENT_TASK_NOT_FOUND.

Source

Thrown at scripts/modules/task-manager/move-task.js:225

	return result;
}

// Helper functions for different move scenarios
function moveSubtaskToSubtask(tasks, sourceId, destinationId) {
	// Parse IDs
	const [sourceParentId, sourceSubtaskId] = sourceId
		.split('.')
		.map((id) => parseInt(id, 10));
	const [destParentId, destSubtaskId] = destinationId
		.split('.')
		.map((id) => parseInt(id, 10));

	// Find source and destination parent tasks
	const sourceParentTask = tasks.find((t) => t.id === sourceParentId);
	const destParentTask = tasks.find((t) => t.id === destParentId);

	if (!sourceParentTask) {
		throw new MoveTaskError(
			MOVE_ERROR_CODES.PARENT_TASK_NOT_FOUND,
			`Source parent task with ID ${sourceParentId} not found`
		);
	}
	if (!destParentTask) {
		throw new MoveTaskError(
			MOVE_ERROR_CODES.PARENT_TASK_NOT_FOUND,
			`Destination parent task with ID ${destParentId} not found`
		);
	}

	// Initialize subtasks arrays if they don't exist (based on commit fixes)
	if (!sourceParentTask.subtasks) {
		sourceParentTask.subtasks = [];
	}
	if (!destParentTask.subtasks) {
		destParentTask.subtasks = [];
	}

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Verify the source task exists in the current tag with `task-master list` before moving
  2. If the task lives in another tag, pass --tag with the correct tag or move cross-tag first
  3. Check the source ID format: '5.2' means parent 5, subtask 2 — parent 5 must exist
  4. Re-read tasks.json to confirm the parent task's numeric id (IDs are stored as numbers)

Example fix

// before (task 12 doesn't exist in this tag)
task-master move --from=12.1 --to=7.3
// after
task-master list  # confirm task exists, then:
task-master move --from=5.1 --to=7.3
Defensive patterns

Strategy: validation

Validate before calling

function assertSourceParent(tasks, sourceId) {
  const parentId = parseInt(String(sourceId).split('.')[0], 10);
  if (!tasks.some((t) => t.id === parentId)) {
    throw new Error(`Source parent task ${parentId} not found in current tag`);
  }
}

Type guard

const parentExists = (tasks, id) =>
  Number.isFinite(id) && tasks.some((t) => t.id === id);

Try / catch

try {
  await moveTask(tasksPath, '5.2', '7.3', false, { projectRoot, tag });
} catch (err) {
  if (err.name === 'MoveTaskError' && err.code === 'PARENT_TASK_NOT_FOUND' && /Source parent/.test(err.message)) {
    console.error('Source parent missing — check `task-master list` and the active --tag');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling moveTask('5.2', '7.3') where no task with id === parseInt('5') exists in the tag's tasks array — the source parent ID is nonexistent, was already moved to another tag, or the ID was mistyped.

Common situations: Referencing a task in the wrong tag (task 5 exists in 'backlog' but not the active tag); task deleted before the move; using a full task ID string where a parent numeric ID is expected.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/a4d8a40a5f458e4d. Report an issue: GitHub.