eyaltoledano/claude-task-master · error
Parent task ${parentId} has no subtasks.
Error message
Parent task ${parentId} has no subtasks. What it means
updateSubtaskById() validates that the parent task exists and that its subtasks array is present before locating the target subtask. This error is thrown when the parent task exists but has no subtasks array (missing or not an array), so there is nothing to update. It is a data-integrity guard against malformed tasks.json entries.
Source
Thrown at scripts/modules/task-manager/update-subtask-by-id.js:163
Number.isNaN(parentId) ||
parentId <= 0 ||
Number.isNaN(subtaskIdNum) ||
subtaskIdNum <= 0
) {
throw new Error(
`Invalid subtask ID format: ${subtaskId}. Both parent ID and subtask ID must be positive integers.`
);
}
const parentTask = data.tasks.find((task) => task.id === parentId);
if (!parentTask) {
throw new Error(
`Parent task with ID ${parentId} not found. Please verify the task ID and try again.`
);
}
if (!parentTask.subtasks || !Array.isArray(parentTask.subtasks)) {
throw new Error(`Parent task ${parentId} has no subtasks.`);
}
const subtaskIndex = parentTask.subtasks.findIndex(
(st) => st.id === subtaskIdNum
);
if (subtaskIndex === -1) {
throw new Error(
`Subtask with ID ${subtaskId} not found. Please verify the subtask ID and try again.`
);
}
const subtask = parentTask.subtasks[subtaskIndex];
// --- Metadata-Only Update (Fast Path) ---
// If only metadata is provided (no prompt), skip AI and just update metadata
if (metadata && (!prompt || prompt.trim() === '')) {
report('info', `Metadata-only update for subtask ${subtaskId}`);
// Merge new metadata with existingView on GitHub (pinned to c0c98d367c)
Solutions
- Run 'task-master list' (or read tasks.json) to confirm the parent task actually has subtasks
- Check the ID format: use parent.subtask (e.g., 5.2); if you meant a top-level task, call update-task-by-id instead
- Use 'task-master expand <id>' to generate subtasks for the parent before updating
- Repair the tasks.json entry so subtasks is an array (backup first)
Example fix
// before
await updateSubtaskById('5.2', prompt);
// after
const parent = tasks.find(t => t.id === 5);
if (parent?.subtasks?.length) {
await updateSubtaskById('5.2', prompt);
} else {
await expandTask(5); // create subtasks first
} Defensive patterns
Strategy: validation
Validate before calling
const parent = data.tasks.find(t => t.id === parentIdNum);
if (!parent) throw new Error(`Task ${parentId} not found`);
if (!Array.isArray(parent.subtasks) || parent.subtasks.length === 0) {
throw new Error(`Task ${parentId} has no subtasks`);
} Type guard
function hasSubtasks(task) {
return Array.isArray(task?.subtasks) && task.subtasks.length > 0;
} Try / catch
try {
await updateSubtaskById('5.2', prompt);
} catch (err) {
if (err.message.includes('has no subtasks')) {
await expandTask(5); // generate subtasks, then retry
} else throw err;
} Prevention
- Always check the parent task's subtasks array before calling update-subtask-by-id
- Use 'task-master list --with-subtasks' to confirm IDs before scripted updates
- Never hand-edit tasks.json without validating the resulting shape
- Prefer 'task-master expand' to create subtasks rather than manual edits
When it happens
Trigger: Calling updateSubtaskById with a subtask ID like '5.2' where task 5 exists but has no subtasks array (e.g., an empty or manually-edited tasks.json, or task 5 never had subtasks created).
Common situations: Typos in the parent ID (meant 5.2 but task 5 has no children); hand-editing or migrating tasks.json and dropping the subtasks field; calling with a display/numeric parent ID assuming subtasks exist; stale file after another process rewrote tasks.
Related errors
- Subtask with ID ${subtaskId} not found. Please verify the su
- Task description is required
- Task status is required
- Parent task ${parentId} not found
- Subtask ${subtaskId} not found in parent task ${parentId}
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/ff9bbb2e3aae29c4.
Report an issue: GitHub.