eyaltoledano/claude-task-master · error
Generated subtasks must have unique ids
Error message
Generated subtasks must have unique ids
What it means
ensureSequentialSubtaskIds() also enforces that all generated subtask ids are distinct. It builds a Set of ids and compares size; duplicates mean the AI returned two subtasks sharing an id, which would collide in tasks.json. Thrown before any data is persisted, so the task file stays intact.
Solutions
- Retry the operation — regenerate the subtasks; duplicates are usually a one-off sampling artifact.
- Deduplicate before validation if you control the pipeline: const seen = new Set(); subtasks.filter(s => !seen.has(s.id) && seen.add(s.id)).
- Switch to a model that reliably produces schema-conformant JSON, or strengthen the prompt instruction to use strictly increasing ids.
- Lower the requested subtask count (reduce complexity threshold) to make valid output more likely.
Example fix
// before
[{ "id": 1, "title": "a" }, { "id": 1, "title": "b" }]
// after
[{ "id": 1, "title": "a" }, { "id": 2, "title": "b" }] Defensive patterns
Strategy: validation
Validate before calling
function hasNoDuplicateIds(subtasks) {
const ids = subtasks.map((s) => s.id);
return new Set(ids).size === ids.length;
}
if (!hasNoDuplicateIds(generated.subtasks)) {
const seen = new Set();
generated.subtasks = generated.subtasks.filter((s) => !seen.has(s.id) && seen.add(s.id));
} Type guard
function idsAreUnique(subtasks) {
const ids = subtasks.map((s) => s.id);
return ids.every((id, i) => ids.indexOf(id) === i) && ids.every((id) => Number.isInteger(id) && id >= 1);
} Try / catch
try {
await scopeDownTask([taskId], strength);
} catch (err) {
if (err.message.includes('must have unique ids')) {
console.error('Duplicate subtask IDs from AI generation — rerun the scope operation');
} else throw err;
} Prevention
- Deduplicate AI output by id before any persistence step
- Request fewer subtasks per generation to reduce duplicate sampling
- Strengthen prompts with explicit 'unique strictly increasing integer ids' instructions
- Retain a JSON schema for subtask output and validate against it before use
When it happens
Trigger: scopeUpTask/scopeDownTask flows where the model returns duplicate ids such as [{id:1},{id:1},{id:2}], commonly when the model is asked for many subtasks and repeats an index, or when string vs number coercion masks duplicates ('1' vs 1 mapping to the same value after parsing).
Common situations: Large complexity-based expansions requesting 10+ subtasks from a weaker model, retries that merge old and new subtask lists without deduplication, or custom output parsing that doesn't dedupe.
Related errors
- Generated object does not match schema
- Generated subtask ids must be positive integers
- Generated subtask ids must be sequential starting from 1
- All subtasks for task
- All tasks parameter must be an array
AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29).
Data as JSON: /api/errors/95861b59db4dd25f.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/modules/task-manager/scope-adjustment.js:456
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
* @param {Object} task - The task to adjust
* @param {string} direction - 'up' or 'down'
* @param {string} strength - 'light', 'regular', or 'heavy'
* @param {string} customPrompt - Optional custom instructionsView on GitHub (pinned to c0c98d367c)