{"record":{"id":"e84a0daf96d51811","repo":"eyaltoledano/claude-task-master","slug":"invalid-subtask-id-format-subtaskid-expected","errorCode":null,"errorMessage":"Invalid subtask ID format: ${subtaskId}. Expected format: parentId.subtaskId","messagePattern":"Invalid subtask ID format: (.+?)\\. Expected format: parentId\\.subtaskId","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts","lineNumber":508,"sourceCode":"\t\t\toldStatus,\n\t\t\tnewStatus,\n\t\t\ttaskId: String(taskId)\n\t\t};\n\t}\n\n\t/**\n\t * Update subtask status within file storage - handles parent status auto-adjustment\n\t */\n\tprivate async updateSubtaskStatusInFile(\n\t\ttasks: Task[],\n\t\tsubtaskId: string,\n\t\tnewStatus: TaskStatus,\n\t\ttag?: string\n\t): Promise<UpdateStatusResult> {\n\t\t// Parse the subtask ID to get parent ID and subtask ID\n\t\tconst parts = subtaskId.split('.');\n\t\tif (parts.length !== 2) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid subtask ID format: ${subtaskId}. Expected format: parentId.subtaskId`\n\t\t\t);\n\t\t}\n\n\t\tconst [parentId, subIdRaw] = parts;\n\t\tconst subId = subIdRaw.trim();\n\t\tif (!/^\\d+$/.test(subId)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid subtask ID: ${subId}. Subtask ID must be a positive integer.`\n\t\t\t);\n\t\t}\n\t\tconst subtaskNumericId = Number(subId);\n\n\t\t// Find the parent task\n\t\tconst parentTaskIndex = tasks.findIndex(\n\t\t\t(t) => String(t.id) === String(parentId)\n\t\t);\n","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/storage/adapters/file-storage/file-storage.ts#L490-L526","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait storage.updateTaskStatus('1.2.3', 'done'); // invalid: two dots\n// after\nconst id = '1.2'; // correct parentId.subtaskId form\nif (!/^\\d+\\.\\d+$/.test(id)) throw new Error(`Bad subtask id: ${id}`);\nawait storage.updateTaskStatus(id, 'done');","handlingStrategy":"validation","validationCode":"function isValidSubtaskId(id: unknown): id is string {\n  return typeof id === 'string' && /^\\d+\\.\\d+$/.test(id);\n}\n// guard: if (!isValidSubtaskId(id)) throw new Error(`Expected parentId.subtaskId, got: ${id}`);","typeGuard":"function isInvalidSubtaskFormatError(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('Invalid subtask ID format:');\n}","tryCatchPattern":"try {\n  await storage.updateTaskStatus(subtaskId, newStatus);\n} catch (e) {\n  if (isInvalidSubtaskFormatError(e)) {\n    // normalize or re-prompt for the ID in 'parentId.subtaskId' form\n  } else throw e;\n}","preventionTips":["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"],"tags":["validation","subtask","id-format"],"backgroundTag":"invalid-id-format","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}