eyaltoledano/claude-task-master · error · Error

Parent task ${parentId} not found

Error message

Parent task ${parentId} not found

What it means

FileStorage.updateSubtaskStatusInFile parses a dotted subtask ID like '5.2', then looks for a parent task whose id matches the '5' portion in the loaded task list. When no parent task matches, it throws this error and the status update is aborted without writing anything. It is a data-existence error: the subtask ID references a parent that is not present under the active tag.

Source

Thrown at packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts:528

			);
		}

		const [parentId, subIdRaw] = parts;
		const subId = subIdRaw.trim();
		if (!/^\d+$/.test(subId)) {
			throw new Error(
				`Invalid subtask ID: ${subId}. Subtask ID must be a positive integer.`
			);
		}
		const subtaskNumericId = Number(subId);

		// Find the parent task
		const parentTaskIndex = tasks.findIndex(
			(t) => String(t.id) === String(parentId)
		);

		if (parentTaskIndex === -1) {
			throw new Error(`Parent task ${parentId} not found`);
		}

		const parentTask = tasks[parentTaskIndex];

		// Find the subtask within the parent task
		const subtaskIndex = parentTask.subtasks.findIndex(
			(st) => st.id === subtaskNumericId || String(st.id) === subId
		);

		if (subtaskIndex === -1) {
			throw new Error(
				`Subtask ${subtaskId} not found in parent task ${parentId}`
			);
		}

		const oldStatus = parentTask.subtasks[subtaskIndex].status || 'pending';
		if (oldStatus === newStatus) {
			return {

View on GitHub (pinned to c0c98d367c)

Solutions

  1. List the tasks under the current tag (storage.getTasks(tag)) and confirm the parent ID exists before updating the subtask.
  2. Verify you are operating on the correct tag — pass the same tag to updateTaskStatus that contains the parent task.
  3. Re-fetch current task IDs if they were cached; IDs change when tasks are reorganized or files are re-generated.
  4. Create the parent task first if it genuinely does not exist yet.

Example fix

// before
await storage.updateTaskStatus('5.2', 'done');
// after
const tasks = await storage.getTasks(tag);
if (!tasks.some((t) => String(t.id) === '5')) {
  throw new Error('Parent task 5 does not exist under tag ' + tag);
}
await storage.updateTaskStatus('5.2', 'done', tag);
Defensive patterns

Strategy: validation

Validate before calling

const tasks = await storage.getTasks(tag);
if (!tasks.some((t) => String(t.id) === String(parentId))) {
  throw new Error(`Parent task ${parentId} does not exist under tag ${tag}`);
}

Type guard

function parentTaskExists(tasks: Task[], parentId: string): tasks is Task[] & { found: true } {
  return tasks.some((t) => String(t.id) === String(parentId));
}

Try / catch

try {
  await storage.updateTaskStatus('5.2', 'done', tag);
} catch (err) {
  if (err instanceof Error && /Parent task .* not found/.test(err.message)) {
    console.warn(`Skipping 5.2: parent missing under tag ${tag}`);
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling storage.updateTaskStatus('5.2', 'done') (which routes to updateSubtaskStatusInFile) when task 5 does not exist in the tasks file for the given tag; calling with a parent ID that was deleted; calling while a different --tag is active so the parent lives under another tag; calling before the parent task was created or after tasks.json was manually edited.

Common situations: Scripts hardcoding subtask IDs that were renumbered after tasks were reorganized; switching tags (e.g. from 'master' to a feature tag) where the parent only exists in the other tag; manual edits to tasks.json removing tasks while automation still references old IDs; off-by-one or stale IDs cached from a previous API response.

Related errors


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