eyaltoledano/claude-task-master · error

Tag '${tag}' not found or has no tasks.

Error message

Tag '${tag}' not found or has no tasks.

What it means

removeTask works on the full tagged tasks.json structure. After resolving the tag (explicit option or active tag), if fullTaggedData has no entry for that tag or the tag entry has no tasks array, this error is thrown.

Source

Thrown at scripts/modules/task-manager/remove-task.js:45

	if (taskIdsToRemove.length === 0) {
		results.success = false;
		results.errors.push('No valid task IDs provided.');
		return results;
	}

	try {
		// Read the tasks file ONCE before the loop, preserving the full tagged structure
		const rawData = readJSON(tasksPath, projectRoot, tag); // Read raw data
		if (!rawData) {
			throw new Error(`Could not read tasks file at ${tasksPath}`);
		}

		// Use the full tagged data if available, otherwise use the data as is
		const fullTaggedData = rawData._rawTaggedData || rawData;

		if (!fullTaggedData[tag] || !fullTaggedData[tag].tasks) {
			throw new Error(`Tag '${tag}' not found or has no tasks.`);
		}

		const tasks = fullTaggedData[tag].tasks; // Work with tasks from the correct tag

		const tasksToDeleteFiles = []; // Collect IDs of main tasks whose files should be deleted

		for (const taskId of taskIdsToRemove) {
			// Check if the task ID exists *before* attempting removal
			if (!taskExists(tasks, taskId)) {
				const errorMsg = `Task with ID ${taskId} in tag '${tag}' not found or already removed.`;
				results.errors.push(errorMsg);
				results.success = false; // Mark overall success as false if any error occurs
				continue; // Skip to the next ID
			}

			try {
				// Handle subtask removal (e.g., '5.2')
				if (typeof taskId === 'string' && taskId.includes('.')) {

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Run 'task-master tags' to list valid tags and use the correct one with --tag.
  2. Remove the task under the existing 'master' tag if you did not intend a custom tag.
  3. Create the missing tag with 'task-master tags create <name>' before operating on it.
  4. Migrate legacy untagged tasks.json to tagged format if required.

Example fix

// before
task-master remove-task --i=5 --tag=featuer-x
// after
task-master remove-task --i=5 --tag=feature-x
Defensive patterns

Strategy: validation

Validate before calling

const data = JSON.parse(fs.readFileSync(tasksPath, 'utf8'));
const activeTag = tag ?? data.activeTag ?? 'master';
if (!data[activeTag]?.tasks) {
  throw new Error(`Tag '${activeTag}' missing or empty. Valid tags: ${Object.keys(data).filter((k) => data[k]?.tasks).join(', ')}`);
}

Type guard

function tagHasTasks(data, tag) {
  return data != null && Array.isArray(data[tag]?.tasks);
}

Try / catch

try {
  await tmCore.tasks.removeTask(tasksPath, ids, { tag });
} catch (err) {
  if (err.message.includes('not found or has no tasks')) {
    console.error(`Tag '${tag}' does not exist or is empty. Run 'task-master tags' to list tags.`);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling removeTask while the resolved tag (e.g. 'feature-x') does not exist in tasks.json, or the tag exists as an empty object without tasks, or reading legacy untagged files where the expected tag key is absent.

Common situations: Typo in --tag name, removing tasks in a tag created later deleted, legacy tasks.json without tag structure being accessed with a non-default tag, tag renamed via task-master tags while old scripts still reference it.

Related errors


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