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
- Pass an existingTaskId to convert an existing task, or
- Pass a newSubtaskData object (e.g. { title, description, ... }) to create a new subtask.
- 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
- Validate option objects before calling addSubtask
- Avoid building options dynamically without a final shape check
- Document both call modes (convert vs create) in wrapper functions
- Use exactOptionalPropertyTypes-style strictness in TS wrappers
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
- streamObjectService requires a schema parameter
- All subtasks for task ${taskId} are already completed. Nothi
- Invalid task ID format: "${trimmedId}". Expected format: "15
- Empty file path provided
- All tasks parameter must be an array
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/32381ea2ec391e2b.
Report an issue: GitHub.