eyaltoledano/claude-task-master · error

INVALID_TASK_ID

INVALID_TASK_ID

Error message

The following tasks were not found${tag ? ` in tag '${tag}'` : ''}: ${invalidTasks.join(', ')}

What it means

removeTaskDirect pre-validates that every requested id exists in the tasks file for the active tag. If any ids do not resolve to real tasks, it aborts atomically with INVALID_TASK_ID listing all missing ids rather than partially deleting.

Source

Thrown at mcp-server/src/core/direct-functions/remove-task.js:84

		if (!data || !data.tasks) {
			return {
				success: false,
				error: {
					code: 'INVALID_TASKS_FILE',
					message: `No valid tasks found in ${tasksJsonPath}${tag ? ` for tag '${tag}'` : ''}`
				}
			};
		}

		const invalidTasks = taskIdArray.filter(
			(taskId) => !taskExists(data.tasks, taskId)
		);

		if (invalidTasks.length > 0) {
			return {
				success: false,
				error: {
					code: 'INVALID_TASK_ID',
					message: `The following tasks were not found${tag ? ` in tag '${tag}'` : ''}: ${invalidTasks.join(', ')}`
				}
			};
		}

		// Enable silent mode to prevent console logs from interfering with JSON response
		enableSilentMode();

		try {
			// Call removeTask with proper context including tag
			const result = await removeTask(tasksJsonPath, id, {
				projectRoot,
				tag
			});

			if (!result.success) {
				return {
					success: false,

View on GitHub (pinned to c0c98d367c)

Solutions

  1. List current tasks (get_tasks / task-master list) and retry remove_task with only ids that exist under the active tag
  2. Switch to the correct tag argument if the tasks live in another tag
  3. Remove the invalid ids from the comma-separated list and keep only valid ones
  4. If the task was already removed, treat this as success and skip the duplicate call

Example fix

// before
await client.callTool('remove_task', { id: '5,12' }); // 12 no longer exists

// after
await client.callTool('remove_task', { id: '5', projectRoot: '/path/to/project' });
Defensive patterns

Strategy: validation

Validate before calling

const existing = new Set(tasks.map(t => String(t.id)));
const invalid = ids.filter(i => !existing.has(String(i)));
if (invalid.length > 0) throw new Error(`Unknown task ids: ${invalid.join(', ')}`);

Type guard

function allIdsExist(ids, tasks) {
  const known = new Set(tasks.map(t => String(t.id)));
  return Array.isArray(ids) && ids.length > 0 && ids.every(i => known.has(String(i)));
}

Try / catch

try {
  const res = await client.callTool('remove_task', { id: ids.join(','), projectRoot });
  if (res.error?.code === 'INVALID_TASK_ID') {
    const missing = res.error.message.split(':')[1]?.trim();
    console.error(`Re-fetch task list; these ids do not exist in the active tag: ${missing}`);
  }
} catch (e) {
  console.error('remove_task failed:', e.message);
}

Prevention

When it happens

Trigger: Calling remove_task with ids that are absent from tasks.json: already-deleted ids, out-of-range numeric ids, typos, comma-separated lists where one id is stale, or ids that exist only in a different tag than the one selected.

Common situations: An agent cached old task ids that were renumbered after updates; user removed tasks in the CLI then repeats the call in MCP; cross-tag confusion (id 3 exists in tag 'backlog' but active tag is 'master'); fat-fingered id like '99' in a 20-task project.

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/342bf95cff7f090b. Report an issue: GitHub.