{"record":{"id":"4530991f84430f40","repo":"eyaltoledano/claude-task-master","slug":"input-validation-error-453099","errorCode":"INPUT_VALIDATION_ERROR","errorMessage":"Task ID is required","messagePattern":"Task ID is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mcp-server/src/core/direct-functions/expand-task.js","lineNumber":84,"sourceCode":"\t\t\t\tcode: 'MISSING_ARGUMENT',\n\t\t\t\tmessage: 'tasksJsonPath is required'\n\t\t\t}\n\t\t};\n\t}\n\n\t// Use provided path\n\tconst tasksPath = tasksJsonPath;\n\n\tlog.info(`[expandTaskDirect] Using tasksPath: ${tasksPath}`);\n\n\t// Validate task ID\n\tconst taskId = id ? parseInt(id, 10) : null;\n\tif (!taskId) {\n\t\tlog.error('Task ID is required');\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: {\n\t\t\t\tcode: 'INPUT_VALIDATION_ERROR',\n\t\t\t\tmessage: 'Task ID is required'\n\t\t\t}\n\t\t};\n\t}\n\n\t// Process other parameters\n\tconst numSubtasks = num ? parseInt(num, 10) : undefined;\n\tconst useResearch = research === true;\n\tconst additionalContext = prompt || '';\n\tconst forceFlag = force === true;\n\n\ttry {\n\t\tlog.info(\n\t\t\t`[expandTaskDirect] Expanding task ${taskId} into ${numSubtasks || 'default'} subtasks. Research: ${useResearch}, Force: ${forceFlag}`\n\t\t);\n\n\t\t// Read tasks data\n\t\tlog.info(`[expandTaskDirect] Attempting to read JSON from: ${tasksPath}`);","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/mcp-server/src/core/direct-functions/expand-task.js#L66-L102","documentation":"expandTaskDirect parses the 'id' argument with parseInt and requires a truthy numeric task ID. Missing, non-numeric, or zero-resolving values produce this INPUT_VALIDATION_ERROR. Note parseInt returns NaN for non-numeric strings, and NaN/0 are both falsy, so any malformed ID fails here.","triggerScenarios":"Calling expand_task with id omitted, id: 'abc' (NaN), id: '0', or a subtask-style ID like '3.1' whose parseFloat/parseInt handling yields an unexpected falsy value at this validation point.","commonSituations":"MCP clients sending the LLM-generated ID with formatting ('Task 3'), users attempting to expand subtasks via the plain task path, or UIs passing empty strings when no task is selected.","solutions":["Pass a positive integer string for a top-level task, e.g. id: '3'.","To expand a subtask, use the dedicated subtask expansion path/parameters rather than passing '3.1' here.","Sanitize the ID client-side: strip non-digits and verify parseInt > 0 before calling.","Check tasks.json to confirm the task ID exists (IDs are 1-based)."],"exampleFix":"// before\nawait expandTaskDirect({ tasksJsonPath, id: 'task 3' }); // parseInt -> NaN\n// after\nconst num = parseInt('3', 10); // 3\nawait expandTaskDirect({ tasksJsonPath, id: String(num) });","handlingStrategy":"type-guard","validationCode":"function normalizeTaskId(raw) {\n  const n = parseInt(String(raw ?? '').replace(/[^0-9]/g, ''), 10);\n  if (!Number.isInteger(n) || n <= 0) throw new Error(`invalid task id: ${raw}`);\n  return String(n);\n}","typeGuard":"function isValidTaskId(v) {\n  const n = parseInt(v, 10);\n  return Number.isInteger(n) && n > 0;\n}","tryCatchPattern":"if (!isValidTaskId(id)) {\n  return { success: false, error: { code: 'INPUT_VALIDATION_ERROR', message: 'Task ID is required' } };\n}\nconst res = await expandTaskDirect({ tasksJsonPath, id });","preventionTips":["Sanitize LLM/user-supplied IDs down to bare digits before calling.","Treat subtask IDs ('3.1') as a different code path, not input to this validation.","Remember IDs are 1-based; never pass 0 or empty strings.","Show a task picker/list in UIs so IDs come from real data."],"tags":["mcp-server","validation","task-id","input-validation"],"backgroundTag":"invalid-task-id","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}