eyaltoledano/claude-task-master · error

For file storage, taskId must be a positive integer. Use upd

Error message

For file storage, taskId must be a positive integer. Use update-subtask-by-id for IDs like "1.2", or run in API storage for display IDs (e.g., "HAM-123").

What it means

When using file storage, updateTaskById() only accepts strictly numeric task IDs (matching /^\d+$/). Alphanumeric or dotted display IDs like 'HAM-123' or '1.2' are rejected because file-based tasks.json keys tasks by integer id; subtask-style IDs belong to update-subtask-by-id and display IDs to API storage.

Source

Thrown at scripts/modules/task-manager/update-task-by-id.js:140

		if (remoteResult) {
			return remoteResult;
		}
		// Otherwise fall through to file-based logic below
		// --- End BRIDGE ---

		// For file storage, ensure the tasks file exists
		if (!fs.existsSync(tasksPath))
			throw new Error(`Tasks file not found: ${tasksPath}`);
		// --- End Input Validations ---

		// --- Task Loading and Status Check (Keep existing) ---
		const data = readJSON(tasksPath, projectRoot, tag);
		if (!data || !data.tasks)
			throw new Error(`No valid tasks found in ${tasksPath}.`);
		// File storage requires a strict numeric task ID
		const idStr = String(taskId).trim();
		if (!/^\d+$/.test(idStr)) {
			throw new Error(
				'For file storage, taskId must be a positive integer. ' +
					'Use update-subtask-by-id for IDs like "1.2", or run in API storage for display IDs (e.g., "HAM-123").'
			);
		}
		const numericTaskId = Number(idStr);
		const taskIndex = data.tasks.findIndex((task) => task.id === numericTaskId);
		if (taskIndex === -1) {
			report('error', `Task with ID ${numericTaskId} not found`);
			throw new Error(`Task with ID ${numericTaskId} not found.`);
		}
		const taskToUpdate = data.tasks[taskIndex];
		if (taskToUpdate.status === 'done' || taskToUpdate.status === 'completed') {
			report(
				'warn',
				`Task ${taskId} is already marked as done and cannot be updated`
			);

			// Only show warning box for text output (CLI)

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Use a plain integer ID (e.g., '5') with updateTaskById in file storage
  2. For dotted subtask IDs ('1.2'), call updateSubtaskById instead
  3. For display IDs ('HAM-123'), run against API (Hamster) storage rather than file storage
  4. Normalize/parse the incoming ID in your script to extract the numeric portion when appropriate

Example fix

// before
await updateTaskById('1.2', prompt); // rejected in file storage
// after
await updateSubtaskById('1.2', prompt); // subtask update
// or
await updateTaskById(1, prompt); // numeric parent ID
Defensive patterns

Strategy: validation

Validate before calling

function routeUpdate(taskId) {
  const id = String(taskId).trim();
  if (/^\d+$/.test(id)) return updateTaskById(Number(id), prompt);
  if (/^\d+\.\d+$/.test(id)) return updateSubtaskById(id, prompt);
  throw new Error(`ID '${taskId}' requires API storage; numeric IDs only for file storage`);
}

Type guard

function isNumericTaskId(taskId) {
  return /^\d+$/.test(String(taskId).trim());
}

Try / catch

try {
  await updateTaskById(taskId, prompt);
} catch (err) {
  if (err.message.includes('must be a positive integer')) {
    console.error('Use update-subtask-by-id for 1.2-style IDs, or Hamster/API storage for HAM-123');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling updateTaskById('1.2', prompt) instead of updateSubtaskById; calling with 'HAM-123' while configured for file storage; passing strings with whitespace-plus-suffix like '5 ' handled, but 'task-5' or '5.0' rejected.

Common situations: Copy-pasting display IDs from Hamster/API-backed views into a local file-storage project; mixing up update-task-by-id and update-subtask-by-id; scripts written against API storage run against file storage.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/1b2efdeb029c5220. Report an issue: GitHub.