{"record":{"id":"dd6ceae202cc5c48","repo":"eyaltoledano/claude-task-master","slug":"no-valid-task-ids-provided","errorCode":null,"errorMessage":"No valid task IDs provided","messagePattern":"No valid task IDs provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tm-core/src/modules/tasks/validation/task-id.ts","lineNumber":127,"sourceCode":" *\n * @example\n * ```typescript\n * parseTaskIds(\"1, 2, 3\");     // [\"1\", \"2\", \"3\"]\n * parseTaskIds(\"1.2,3.4\");     // [\"1.2\", \"3.4\"]\n * parseTaskIds(\"HAM-123\");     // [\"HAM-123\"]\n * parseTaskIds(\"ham1,ham2\");   // [\"HAM-1\", \"HAM-2\"] (normalized)\n * parseTaskIds(\"invalid\");     // throws Error\n * parseTaskIds(\"HAM-1.2\");     // throws Error (API subtasks not supported)\n * ```\n */\nexport function parseTaskIds(input: string): string[] {\n\tconst ids = input\n\t\t.split(',')\n\t\t.map((id) => id.trim())\n\t\t.filter((id) => id.length > 0);\n\n\tif (ids.length === 0) {\n\t\tthrow new Error('No valid task IDs provided');\n\t}\n\n\tconst invalidIds = ids.filter((id) => !isValidTaskIdFormat(id));\n\tif (invalidIds.length > 0) {\n\t\tthrow new Error(\n\t\t\t`Invalid task ID format: ${invalidIds.join(', ')}. Expected numeric (e.g., '15'), subtask (e.g., '15.2'), or display ID (e.g., 'HAM-123')`\n\t\t);\n\t}\n\n\t// Normalize all IDs (e.g., \"ham1\" → \"HAM-1\")\n\treturn ids.map(normalizeDisplayId);\n}\n\n/**\n * Extract parent task ID from a subtask ID\n *\n * @param taskId - Task ID (e.g., \"1.2.3\")\n * @returns Parent ID (e.g., \"1\") or the original ID if not a subtask","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/packages/tm-core/src/modules/tasks/validation/task-id.ts#L109-L145","documentation":"parseTaskIds() in tm-core's task-id validation splits a comma-separated ID string, trims and drops empty segments, and throws a plain Error('No valid task IDs provided') if nothing remains. It is an input-validation guard so callers never proceed with an empty ID set.","triggerScenarios":"Passing an empty string, whitespace-only string, or a string of only commas (e.g. ',,,' or ' , ') to `parseTaskIds()`.","commonSituations":"CLI flag defaults like `--id \"\"`; shell variable interpolation that expands to empty (`tm tasks update --id \"$IDS\"` with unset IDS); UI passing an empty selection array joined into a string.","solutions":["Check the ID input is non-empty (after trimming and comma-splitting) before calling parseTaskIds","Fix the shell/variable that produced an empty value (e.g. `${IDS:?IDS is required}`)","If empty should be allowed, handle it at the call site before invoking the parser"],"exampleFix":"// before\nconst ids = parseTaskIds(process.env.TASK_IDS ?? ''); // throws when unset\n// after\nconst raw = process.env.TASK_IDS;\nif (!raw?.trim()) throw new Error('TASK_IDS env var is required');\nconst ids = parseTaskIds(raw);","handlingStrategy":"validation","validationCode":"const raw = (input ?? '').trim();\nif (!raw || raw.split(',').every(s => s.trim() === '')) {\n  throw new Error('Provide at least one task ID');\n}\nparseTaskIds(raw); // safe to call","typeGuard":"function hasTaskIds(input: string | undefined | null): input is string {\n  return !!input && input.split(',').some(id => id.trim().length > 0);\n}","tryCatchPattern":"try {\n  ids = parseTaskIds(rawInput);\n} catch (e) {\n  if (e.message === 'No valid task IDs provided') {\n    printUsage('--id requires at least one task ID');\n    process.exitCode = 1;\n    return;\n  }\n  throw e;\n}","preventionTips":["Guard env vars/CLI flags with ${VAR:?} or explicit required checks","Never pass user selections joined with '' — always trim and drop empties first","Give CLI flags explicit required:true so the framework rejects empty input","Validate before invoking the parser in interactive UIs"],"tags":["validation","input","task-ids"],"backgroundTag":"empty-input-validation","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}