eyaltoledano/claude-task-master · error
Invalid subtask ID format: ${subtaskId}. Expected format: "p
Error message
Invalid subtask ID format: ${subtaskId}. Expected format: "parentId.subtaskId" What it means
removeSubtask only accepts dot-notation subtask IDs like '5.2' (parent.subtask). If the provided subtaskId does not contain a '.', it cannot identify which parent to look under, so this error is thrown.
Source
Thrown at scripts/modules/task-manager/remove-subtask.js:33
tasksPath,
subtaskId,
convertToTask = false,
generateFiles = false,
context = {}
) {
const { projectRoot, tag } = context;
try {
log('info', `Removing subtask ${subtaskId}...`);
// Read the existing tasks with proper context
const data = readJSON(tasksPath, projectRoot, tag);
if (!data || !data.tasks) {
throw new Error(`Invalid or missing tasks file at ${tasksPath}`);
}
// Parse the subtask ID (format: "parentId.subtaskId")
if (!subtaskId.includes('.')) {
throw new Error(
`Invalid subtask ID format: ${subtaskId}. Expected format: "parentId.subtaskId"`
);
}
const [parentIdStr, subtaskIdStr] = subtaskId.split('.');
const parentId = parseInt(parentIdStr, 10);
const subtaskIdNum = parseInt(subtaskIdStr, 10);
// Find the parent task
const parentTask = data.tasks.find((t) => t.id === parentId);
if (!parentTask) {
throw new Error(`Parent task with ID ${parentId} not found`);
}
// Check if parent has subtasks
if (!parentTask.subtasks || parentTask.subtasks.length === 0) {
throw new Error(`Parent task ${parentId} has no subtasks`);
}View on GitHub (pinned to c0c98d367c)
Solutions
- Use dot-notation: remove-subtask 5.2 instead of 5.
- To delete a main task, use remove-task with the plain task ID instead.
- Find the correct parent ID with 'task-master list' or show, then rebuild the parent.subtaskId string.
Example fix
// before task-master remove-subtask --i=7 // after task-master remove-subtask --i=3.7
Defensive patterns
Strategy: validation
Validate before calling
if (typeof subtaskId !== 'string' || !/^\d+\.\d+$/.test(subtaskId.trim())) {
throw new Error(`subtaskId must be parent.subtask format, got: ${subtaskId}`);
} Type guard
function isDotSubtaskId(v: unknown): v is string {
return typeof v === 'string' && /^\d+\.\d+$/.test(v);
} Try / catch
try {
await tmCore.tasks.removeSubtask(tasksPath, subtaskId);
} catch (err) {
if (err.message.includes('Invalid subtask ID format')) {
console.error(`'${subtaskId}' is not parent.subtask — use remove-task for main task IDs, or pass e.g. 5.2.`);
} else throw err;
} Prevention
- Remember remove-subtask only takes dot-notation IDs; remove-task handles main IDs.
- Copy IDs directly from 'task-master list' output instead of typing them.
- Normalize/validate ID input in scripts before calling the API.
- Trim whitespace from CLI args before passing IDs.
When it happens
Trigger: Calling removeSubtask('5') or removeSubtask('subtask-name') — an ID without a dot separator — where a main task ID or non-numeric label was passed instead of a parent.subtask ID.
Common situations: Confusing remove-subtask with remove-task (the latter handles main task IDs), passing a subtask's standalone ID instead of its parent-scoped ID, copying the wrong ID from task listings.
Related errors
- Invalid maxAttempts value: ${maxAttempts}. Must be a positiv
- Parent task with ID ${parentId} not found
- Parent task ${parentId} has no subtasks
- Subtask ${subtaskId} not found
- Parent task ${parentTaskId} or its subtasks not found for su
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/5a26875541e1c692.
Report an issue: GitHub.