eyaltoledano/claude-task-master · error

Generated subtask ids must be positive integers

Error message

Generated subtask ids must be positive integers

What it means

ensureSequentialSubtaskIds() validates the subtask array produced by AI-driven scope adjustments. Each subtask.id must be an integer >= 1; if the LLM-generated or parsed output contains 0, negative numbers, floats, or non-numeric ids, this error is thrown before the data is written. It is a guard against corrupting tasks.json with malformed subtask ids.

Source

Thrown at scripts/modules/task-manager/scope-adjustment.js:452

		// Don't fail the whole operation if subtask regeneration fails
		return {
			updatedTask: task,
			regenerated: false,
			preserved: preservedSubtasks.length,
			generated: 0,
			error: error.message
		};
	}
}

function ensureSequentialSubtaskIds(subtasks) {
	if (!Array.isArray(subtasks) || subtasks.length === 0) {
		return;
	}

	const ids = subtasks.map((subtask) => subtask.id);
	if (ids.some((id) => !Number.isInteger(id) || id < 1)) {
		throw new Error('Generated subtask ids must be positive integers');
	}
	const uniqueIds = new Set(ids);
	if (uniqueIds.size !== ids.length) {
		throw new Error('Generated subtasks must have unique ids');
	}

	const sortedIds = [...uniqueIds].sort((a, b) => a - b);
	for (let index = 0; index < sortedIds.length; index += 1) {
		if (sortedIds[index] !== index + 1) {
			throw new Error(
				'Generated subtask ids must be sequential starting from 1'
			);
		}
	}
}

/**
 * Generates AI prompt for scope adjustment

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Re-run the scope-up/scope-down command; LLM output variance often produces valid ids on retry.
  2. Use a stronger model (e.g. switch the research/complexity role model in .taskmaster/config.json) that follows the JSON schema reliably.
  3. Inspect the raw model response (enable debug logging) to see why ids came back invalid, and remove any customPrompt that alters the subtask format.
  4. Validate the generated subtasks yourself before calling, or sanitize ids (map to Math.max(1, Math.round(id))) if your wrapper allows pre-processing.

Example fix

// before (malformed AI output)
{ "subtasks": [{ "id": 0, "title": "a" }, { "id": -2, "title": "b" }] }
// after (valid)
{ "subtasks": [{ "id": 1, "title": "a" }, { "id": 2, "title": "b" }] }
Defensive patterns

Strategy: validation

Validate before calling

function subtaskIdsAreValidInts(subtasks) {
  return Array.isArray(subtasks) && subtasks.length > 0 &&
    subtasks.every((s) => Number.isInteger(s.id) && s.id >= 1);
}
if (!subtaskIdsAreValidInts(generated.subtasks)) {
  // regenerate or repair before calling scope functions
  generated.subtasks.forEach((s, i) => { if (!Number.isInteger(s.id) || s.id < 1) s.id = i + 1; });
}

Type guard

function isValidSubtask(s) {
  return typeof s === 'object' && s !== null && Number.isInteger(s.id) && s.id >= 1;
}

Try / catch

try {
  await scopeUpTask([taskId], strength);
} catch (err) {
  if (err.message.includes('must be positive integers')) {
    console.error('AI returned malformed subtask IDs; retry or switch to a stronger model');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling scopeUpTask/scopeDownTask (via regenerateSubtasksForComplexity) where the model returns JSON with subtask ids like 0, -1, 1.5, "one", or ids omitted (undefined), typically when the AI response is malformed or the parsing step mis-extracts ids.

Common situations: Weak/small LLM models producing off-spec JSON, prompt responses truncated so id fields are lost, custom prompts that change the expected output schema, or API responses wrapped in unexpected formats that break id extraction.

Related errors


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