eyaltoledano/claude-task-master · error

Either existingTaskId or newSubtaskData must be provided

Error message

Either existingTaskId or newSubtaskData must be provided

What it means

addSubtask supports two modes: convert an existing task (existingTaskId) or create a brand-new subtask (newSubtaskData). This error is thrown when neither argument is supplied, so there is no source for the subtask. It is a fail-fast guard before any file mutation.

Source

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

			const newSubtaskId = highestSubtaskId + 1;

			// Create the new subtask object
			newSubtask = {
				id: newSubtaskId,
				title: newSubtaskData.title,
				description: newSubtaskData.description || '',
				details: newSubtaskData.details || '',
				status: newSubtaskData.status || 'pending',
				dependencies: newSubtaskData.dependencies || [],
				parentTaskId: parentIdNum
			};

			// Add to parent's subtasks
			parentTask.subtasks.push(newSubtask);

			log('info', `Created new subtask ${parentIdNum}.${newSubtaskId}`);
		} else {
			throw new Error(
				'Either existingTaskId or newSubtaskData must be provided'
			);
		}

		// Write the updated tasks back to the file with proper context
		writeJSON(tasksPath, data, projectRoot, tag);

		// Note: Task file generation is no longer supported and has been removed

		return newSubtask;
	} catch (error) {
		log('error', `Error adding subtask: ${error.message}`);
		throw error;
	}
}

export default addSubtask;

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Pass an existingTaskId to convert an existing task, or
  2. Pass a newSubtaskData object (e.g. { title, description, ... }) to create a new subtask.
  3. Add argument validation in calling code before invoking addSubtask.

Example fix

// before
await addSubtask('1'); // neither provided
// after
await addSubtask('1', null, { title: 'New subtask', description: '...' });
Defensive patterns

Strategy: validation

Validate before calling

function assertSubtaskSource(opts = {}) {
  const hasExisting = opts.existingTaskId != null;
  const hasNew = opts.newSubtaskData != null && typeof opts.newSubtaskData === 'object';
  if (hasExisting === hasNew) {
    throw new Error('Provide exactly one of existingTaskId or newSubtaskData');
  }
}

Type guard

function hasSubtaskSource(opts) {
  return opts?.existingTaskId != null ||
    (opts?.newSubtaskData != null && typeof opts.newSubtaskData === 'object');
}

Try / catch

try {
  await addSubtask(tasksPath, parentId, opts);
} catch (err) {
  if (err.message.includes('Either existingTaskId or newSubtaskData')) {
    console.error('addSubtask requires existingTaskId or newSubtaskData');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling addSubtask(parentId) with no existingTaskId and no newSubtaskData, or passing null/undefined for both.

Common situations: Programming errors in scripts that build options dynamically and drop the field, CLI parsers not forwarding the argument, or refactors that removed newSubtaskData accidentally.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — 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/32381ea2ec391e2b. Report an issue: GitHub.