{"record":{"id":"c9533c106e282a55","repo":"eyaltoledano/claude-task-master","slug":"invalid-subtask-id-format-subtaskid-in-solo-m","errorCode":null,"errorMessage":"Invalid subtask ID format: ${subtaskId}. In solo mode, subtask ID must be in format \"parentId.subtaskId\" (e.g., \"5.2\").","messagePattern":"Invalid subtask ID format: (.+?)\\. In solo mode, subtask ID must be in format \"parentId\\.subtaskId\" \\(e\\.g\\., \"5\\.2\"\\)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/modules/task-manager/update-subtask-by-id.js","lineNumber":124,"sourceCode":"\t\t\tisMCP,\n\t\t\toutputFormat,\n\t\t\treport\n\t\t});\n\n\t\t// If remote handled it, return the result\n\t\tif (remoteResult) {\n\t\t\treturn {\n\t\t\t\tupdatedSubtask: { id: subtaskId },\n\t\t\t\ttelemetryData: remoteResult.telemetryData,\n\t\t\t\ttagInfo: remoteResult.tagInfo\n\t\t\t};\n\t\t}\n\t\t// Otherwise fall through to file-based logic below\n\t\t// --- End BRIDGE ---\n\n\t\t// For file storage, validate the subtask ID format (must contain a dot)\n\t\tif (!subtaskId.includes('.')) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid subtask ID format: ${subtaskId}. In solo mode, subtask ID must be in format \"parentId.subtaskId\" (e.g., \"5.2\").`\n\t\t\t);\n\t\t}\n\n\t\tif (!fs.existsSync(tasksPath)) {\n\t\t\tthrow new Error(`Tasks file not found at path: ${tasksPath}`);\n\t\t}\n\n\t\tconst data = readJSON(tasksPath, projectRoot, tag);\n\t\tif (!data || !data.tasks) {\n\t\t\tthrow new Error(\n\t\t\t\t`No valid tasks found in ${tasksPath}. The file may be corrupted or have an invalid format.`\n\t\t\t);\n\t\t}\n\n\t\tconst [parentIdStr, subtaskIdStr] = subtaskId.split('.');\n\t\tconst parentId = parseInt(parentIdStr, 10);\n\t\tconst subtaskIdNum = parseInt(subtaskIdStr, 10);","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/scripts/modules/task-manager/update-subtask-by-id.js#L106-L142","documentation":"When the remote/API bridge does not consume the update, file storage requires subtask IDs to contain a dot separating parent and subtask IDs. A dotless ID reaches this check only in solo/file mode and is rejected.","triggerScenarios":"Calling updateSubtaskById('5', ...) in file-storage mode; using an API-style ID ('HAM-2611') against a local file-based project where the remote bridge returned no result.","commonSituations":"Copy-pasting API examples into a solo-mode project, forgetting the parent prefix, or a mixed setup where tryUpdateViaRemote silently fails and the file path runs.","solutions":["Use the 'parentId.subtaskId' format, e.g. '5.2'","Confirm whether your project uses API storage (then a plain task ID may be valid) or file storage","For API-mode IDs, use the update-task path instead of update-subtask"],"exampleFix":"// before\nawait updateSubtaskById('3', prompt, options); // file storage requires a dot\n// after\nawait updateSubtaskById('3.1', prompt, options);","handlingStrategy":"validation","validationCode":"if (!subtaskId.includes('.')) {\n  throw new Error(`Use parentId.subtaskId format, got: ${subtaskId}`);\n}","typeGuard":"function isDottedSubtaskId(v) {\n  return typeof v === 'string' && /^\\d+\\.\\d+$/.test(v);\n}","tryCatchPattern":"try {\n  await updateSubtaskById(subtaskId, prompt, options);\n} catch (err) {\n  if (err.message.startsWith('Invalid subtask ID format')) {\n    console.error('File storage requires dotted IDs like \"5.2\"');\n  } else throw err;\n}","preventionTips":["Use dotted IDs for local/file projects","Use plain task IDs only with API/remote storage","Centralize ID formatting in one helper"],"tags":["validation","id-format"],"backgroundTag":"invalid-id-format","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}