eyaltoledano/claude-task-master · error

Manual task data must include at least a title and descripti

Error message

Manual task data must include at least a title and description.

What it means

addTask() validates manually supplied task data before persisting it. When the user chose the manual path (no --prompt / AI generation), it requires both a non-empty string title and a non-empty string description. If either is missing, empty, or of the wrong type, it refuses to create a malformed task.

Source

Thrown at scripts/modules/task-manager/add-task.js:359

			allRelatedTaskIds.add(taskId);
		}

		let taskData;

		// Check if manual task data is provided
		if (manualTaskData) {
			report('Using manually provided task data', 'info');
			taskData = manualTaskData;
			report('DEBUG: Taking MANUAL task data path.', 'debug');

			// Basic validation for manual data
			if (
				!taskData.title ||
				typeof taskData.title !== 'string' ||
				!taskData.description ||
				typeof taskData.description !== 'string'
			) {
				throw new Error(
					'Manual task data must include at least a title and description.'
				);
			}
		} else {
			report('DEBUG: Taking AI task generation path.', 'debug');
			// --- Refactored AI Interaction ---
			report(`Generating task data with AI with prompt:\n${prompt}`, 'info');

			// --- Use the new ContextGatherer ---
			const contextGatherer = new ContextGatherer(projectRoot, tag);
			const gatherResult = await contextGatherer.gather({
				semanticQuery: prompt,
				dependencyTasks: numericDependencies,
				format: 'research'
			});

			const gatheredContext = gatherResult.context;
			const analysisData = gatherResult.analysisData;

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Provide both a title and a description as non-empty strings in taskData.
  2. If you intended AI generation, pass a prompt (e.g. --prompt "...") so the AI path runs instead of the manual validation.
  3. Validate/sanitize the incoming task payload before calling addTask(), coercing non-string fields to strings or rejecting them.

Example fix

// before
await addTask(tasksPath, { prompt: null, taskData: { title: 'Setup CI' } });
// after
await addTask(tasksPath, { prompt: null, taskData: { title: 'Setup CI', description: 'Add GitHub Actions workflow for tests' } });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof title !== 'string' || !title.trim() || typeof description !== 'string' || !description.trim()) {
  throw new TypeError('Both title and description are required non-empty strings');
}
await addTask(tasksPath, { taskData: { title, description } });

Type guard

function isManualTaskData(v) {
  return !!v && typeof v.title === 'string' && v.title.length > 0 && typeof v.description === 'string' && v.description.length > 0;
}

Try / catch

try {
  await addTask(tasksPath, { taskData });
} catch (err) {
  if (err.message.includes('must include at least a title and description')) {
    console.error('Missing/invalid title or description:', taskData);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling addTask() with { prompt: null } (or no prompt) so the manual branch runs, while passing taskData whose title or description is undefined, an empty string, or a non-string (e.g. a number).

Common situations: CLI invocation like `task-master add-task` without --prompt and without --title/--description; MCP tool call where the client omitted the description field; programmatic use where a form/JSON payload had title but no description.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — 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/19a5d94c864b642e. Report an issue: GitHub.