eyaltoledano/claude-task-master · error

SUBTASK_NOT_FOUND

SUBTASK_NOT_FOUND

Error message

Subtask ${id} or its parent task not found.

What it means

After delegating to the core update logic, updateSubtaskByIdDirect checks the result: if no coreResult comes back or coreResult.updatedSubtask is null, the requested subtask (or its parent task) does not exist in storage and it returns SUBTASK_NOT_FOUND. This is a lookup failure, not an input-format problem — the ID was well-formed but matched nothing.

Source

Thrown at mcp-server/src/core/direct-functions/update-subtask-by-id.js:115

				useResearch,
				{
					mcpLog: logWrapper,
					session,
					projectRoot,
					tag,
					commandName: 'update-subtask',
					outputType: 'mcp',
					metadata
				},
				'json'
			);

			if (!coreResult || coreResult.updatedSubtask === null) {
				const message = `Subtask ${id} or its parent task not found.`;
				logWrapper.error(message);
				return {
					success: false,
					error: { code: 'SUBTASK_NOT_FOUND', message: message }
				};
			}

			const parentId = subtaskIdStr.split('.')[0];
			const successMessage = `Successfully updated subtask with ID ${subtaskIdStr}`;
			logWrapper.success(successMessage);
			return {
				success: true,
				data: {
					message: `Successfully updated subtask with ID ${subtaskIdStr}`,
					subtaskId: subtaskIdStr,
					parentId: parentId,
					subtask: coreResult.updatedSubtask,
					tasksPath,
					useResearch,
					telemetryData: coreResult.telemetryData,
					tagInfo: coreResult.tagInfo
				}

View on GitHub (pinned to c0c98d367c)

Solutions

  1. List tasks (get-tasks tool) to confirm the parent task and subtask index still exist.
  2. Verify tasksJsonPath points at the correct project's tasks file.
  3. Re-derive the subtask ID from current task data rather than a cached/older reference.
  4. For API storage, confirm the ticket ID (e.g. HAM-2611) exists in the remote system.

Example fix

// before
await updateSubtask({ id: '5.2', prompt: 'x', tasksJsonPath }); // subtask gone
// after
const tasks = await getTasks({ tasksJsonPath }); // verify 5.2 exists first
await updateSubtask({ id: '5.2', prompt: 'x', tasksJsonPath });
Defensive patterns

Strategy: validation

Validate before calling

const tasks = JSON.parse(fs.readFileSync(tasksJsonPath, 'utf8')).tasks;
const [pid, sid] = id.split('.').map(Number);
const parent = tasks.find(t => t.id === pid);
if (!parent || !parent.subtasks || !parent.subtasks.some(s => s.id === sid)) {
  throw new Error(`Subtask ${id} not found — refresh task list first`);
}

Type guard

function subtaskExists(tasks, id) {
  const [p, s] = id.split('.').map(Number);
  const parent = tasks.find(t => t.id === p);
  return Boolean(parent && parent.subtasks?.some(x => x.id === s));
}

Try / catch

const res = await updateSubtaskByIdDirect(args);
if (!res.success && res.error.code === 'SUBTASK_NOT_FOUND') {
  const tasks = await getTasks({ tasksJsonPath: args.tasksJsonPath }); // re-sync IDs
}

Prevention

When it happens

Trigger: Requesting subtask '5.2' when task 5 has no second subtask, the parent task was deleted, the ID references a different tasks.json/project, or API storage where the ticket ID does not exist.

Common situations: Stale IDs after re-generating tasks (IDs shifted), pointing tasksJsonPath at another project's tasks file, typos in the parent portion of a dotted ID ('55.2' vs '5.2').

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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