eyaltoledano/claude-task-master · error · Error
Invalid subtask ID format: ${subtaskId}. Expected format: pa
Error message
Invalid subtask ID format: ${subtaskId}. Expected format: parentId.subtaskId What it means
updateSubtaskStatusInFile() expects subtask IDs in the dotted 'parentId.subtaskId' form (e.g. '5.2'). It splits the ID on '.' and requires exactly two segments; anything else — no dot, multiple dots, or empty string — throws this format-validation error before any file access.
Source
Thrown at packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts:508
oldStatus,
newStatus,
taskId: String(taskId)
};
}
/**
* Update subtask status within file storage - handles parent status auto-adjustment
*/
private async updateSubtaskStatusInFile(
tasks: Task[],
subtaskId: string,
newStatus: TaskStatus,
tag?: string
): Promise<UpdateStatusResult> {
// Parse the subtask ID to get parent ID and subtask ID
const parts = subtaskId.split('.');
if (parts.length !== 2) {
throw new Error(
`Invalid subtask ID format: ${subtaskId}. Expected format: parentId.subtaskId`
);
}
const [parentId, subIdRaw] = parts;
const subId = subIdRaw.trim();
if (!/^\d+$/.test(subId)) {
throw new Error(
`Invalid subtask ID: ${subId}. Subtask ID must be a positive integer.`
);
}
const subtaskNumericId = Number(subId);
// Find the parent task
const parentTaskIndex = tasks.findIndex(
(t) => String(t.id) === String(parentId)
);
View on GitHub (pinned to c0c98d367c)
Solutions
- Normalize the ID to exactly 'parentId.subtaskId' (two integer segments separated by one dot)
- Check for deeper nesting: '1.2.3' is invalid here — address only one level
- Validate the ID format with a regex before calling
- If the ID belongs to a plain task, use the regular task status path instead
Example fix
// before
await storage.updateTaskStatus('1.2.3', 'done'); // invalid: two dots
// after
const id = '1.2'; // correct parentId.subtaskId form
if (!/^\d+\.\d+$/.test(id)) throw new Error(`Bad subtask id: ${id}`);
await storage.updateTaskStatus(id, 'done'); Defensive patterns
Strategy: validation
Validate before calling
function isValidSubtaskId(id: unknown): id is string {
return typeof id === 'string' && /^\d+\.\d+$/.test(id);
}
// guard: if (!isValidSubtaskId(id)) throw new Error(`Expected parentId.subtaskId, got: ${id}`); Type guard
function isInvalidSubtaskFormatError(e: unknown): e is Error {
return e instanceof Error && e.message.startsWith('Invalid subtask ID format:');
} Try / catch
try {
await storage.updateTaskStatus(subtaskId, newStatus);
} catch (e) {
if (isInvalidSubtaskFormatError(e)) {
// normalize or re-prompt for the ID in 'parentId.subtaskId' form
} else throw e;
} Prevention
- Normalize all subtask references to a single dotted pair before storage calls
- Reject deeper nesting ('1.2.3') at the input boundary
- Trim whitespace from user-supplied IDs
- Distinguish task vs subtask IDs before routing to updateTaskStatus
When it happens
Trigger: Passing a bare task id like '5' to a subtask status update path, an ID with multiple dots such as '5.2.3', an empty or whitespace ID, or routing a non-subtask task ID into updateTaskStatus when it contains dots.
Common situations: Copy-paste errors mixing task and subtask IDs, deep-nested IDs from another tool that supports sub-subtasks (this adapter supports only one level), or user input not normalized before the call.
Related errors
- Invalid subtask ID: ${subId}. Subtask ID must be a positive
- Invalid iterations: ${iterations}. Must be a positive intege
- Invalid format: ${options.format}. Valid formats are: text,
- PARENT_TASK_NOT_FOUND
- PARENT_TASK_NO_SUBTASKS
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/e84a0daf96d51811.
Report an issue: GitHub.