eyaltoledano/claude-task-master · error · Error

Task ${taskId} not found

Error message

Task ${taskId} not found

What it means

updateTask() loads all tasks for the active tag and searches for one whose id matches taskId. If no task matches, it throws this error rather than silently failing; the caller must supply an ID of an existing task in the current tag.

Source

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

	async appendTasks(tasks: Task[], tag?: string): Promise<void> {
		const existingTasks = await this.loadTasks(tag);
		const allTasks = [...existingTasks, ...tasks];
		await this.saveTasks(allTasks, tag);
	}

	/**
	 * Update a specific task
	 */
	async updateTask(
		taskId: string,
		updates: Partial<Task>,
		tag?: string
	): Promise<void> {
		const tasks = await this.loadTasks(tag);
		const taskIndex = tasks.findIndex((t) => String(t.id) === String(taskId));

		if (taskIndex === -1) {
			throw new Error(`Task ${taskId} not found`);
		}

		const existingTask = tasks[taskIndex];

		// Preserve subtask metadata when subtasks are updated
		// AI operations don't include metadata in returned subtasks
		let mergedSubtasks = updates.subtasks;
		if (updates.subtasks && existingTask.subtasks) {
			mergedSubtasks = updates.subtasks.map((updatedSubtask) => {
				// Type-coerce IDs for comparison; fall back to title match if IDs don't match
				const originalSubtask = existingTask.subtasks?.find(
					(st) =>
						String(st.id) === String(updatedSubtask.id) ||
						(updatedSubtask.title && st.title === updatedSubtask.title)
				);
				// Merge metadata: preserve original and add/override with new
				if (originalSubtask?.metadata || updatedSubtask.metadata) {
					return {

View on GitHub (pinned to c0c98d367c)

Solutions

  1. List tasks in the active tag (tmCore.tasks.get() / 'task-master list') and confirm the ID exists
  2. Pass the correct tag parameter if the task lives in another tag
  3. Re-check whether the task was deleted or completed and removed
  4. If parsing user input, validate the ID format before calling

Example fix

// before
await storage.updateTask('42', updates); // throws if task 42 does not exist
// after
const tasks = await storage.loadTasks();
if (tasks.some((t) => String(t.id) === '42')) {
  await storage.updateTask('42', updates);
}
Defensive patterns

Strategy: validation

Validate before calling

async function taskExists(storage: FileStorage, taskId: string, tag?: string) {
  const tasks = await storage.loadTasks(tag);
  return tasks.some((t) => String(t.id) === String(taskId));
}
// call only if (await taskExists(storage, '42')) ...

Type guard

function isTaskNotFoundError(e: unknown, taskId?: string): e is Error {
  return e instanceof Error &&
    e.message === `Task ${taskId ?? ''} not found` ||
    (e instanceof Error && /^Task .+ not found$/.test(e.message));
}

Try / catch

try {
  await storage.updateTask(taskId, updates);
} catch (e) {
  if (/^Task .+ not found$/.test((e as Error).message)) {
    // refresh task list / inform user the ID no longer exists
  } else throw e;
}

Prevention

When it happens

Trigger: Calling updateTask with an ID that does not exist in the active tag's task list, passing a numeric id as a string with unexpected formatting (though matching is done via String() comparison so both '1' and 1 work), or operating against the wrong tag where the task lives under a different tag.

Common situations: Task was deleted by another process/session before the update, hard-coded task IDs from an old tasks.json, CLI user mistypes an ID, or the default tag differs from the tag the task belongs to.

Related errors


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