{"record":{"id":"96a65d128473c3e0","repo":"ruvnet/ruflo","slug":"duplicate-anchor-task-id-task-id","errorCode":null,"errorMessage":"duplicate anchor task id: ${task.id}","messagePattern":"duplicate anchor task id: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/services/harness-project-anchor.ts","lineNumber":91,"sourceCode":"\nfunction parseTasks(path: string): { version: string; tasks: HumanEvalTask[] } {\n  const parsed = JSON.parse(readFileSync(path, 'utf8')) as {\n    schemaVersion?: string;\n    version?: string;\n    tasks?: HumanEvalTask[];\n  };\n  if (parsed.schemaVersion && parsed.schemaVersion !== PROJECT_ANCHOR_SCHEMA) {\n    throw new Error(`unsupported flywheel anchor schema: ${parsed.schemaVersion}`);\n  }\n  if (!Array.isArray(parsed.tasks) || parsed.tasks.length < 4) {\n    throw new Error('project flywheel anchor requires at least 4 labelled tasks');\n  }\n  const ids = new Set<string>();\n  for (const [index, task] of parsed.tasks.entries()) {\n    if (!task || typeof task.id !== 'string' || !/^[A-Za-z0-9._-]{1,128}$/.test(task.id)) {\n      throw new Error(`invalid anchor task id at index ${index}`);\n    }\n    if (ids.has(task.id)) throw new Error(`duplicate anchor task id: ${task.id}`);\n    ids.add(task.id);\n    if (typeof task.q !== 'string' || task.q.trim().length === 0) {\n      throw new Error(`anchor task ${task.id} has no query`);\n    }\n    if (!Array.isArray(task.labels) || task.labels.length === 0 || task.labels.some((label) => typeof label !== 'string' || !label.trim())) {\n      throw new Error(`anchor task ${task.id} requires non-empty string labels`);\n    }\n  }\n  return { version: parsed.version ?? 'project-anchor-v1', tasks: parsed.tasks };\n}\n\nfunction toSelection(\n  path: string,\n  expectedHash: string,\n): FlywheelAnchorSelection {\n  const parsed = parseTasks(path);\n  const actualHash = humanEvalHash(parsed.tasks);\n  if (actualHash !== normalizeHash(expectedHash)) {","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli/src/services/harness-project-anchor.ts#L73-L109","documentation":"Thrown during anchor parsing when two tasks in the tasks array share the same id. Ids are tracked in a Set as the loop proceeds, so the second occurrence is rejected. Duplicate ids would corrupt downstream evaluation that keys results by task id, so this is enforced as a hard uniqueness constraint.","triggerScenarios":"An anchor file containing two task objects with an identical id string; copy-pasting a task and forgetting to change its id; an id-generation function that produced a collision.","commonSituations":"Duplicating a template task to reach the 4-task minimum without re-id'ing; merging two anchor files that both used generic ids like \"task-1\"; an id normalizer that collapsed two distinct ids to the same sanitized form.","solutions":["Search the tasks array for the id in the error message and rename the duplicate occurrence to a unique value.","If ids are generated, ensure the generator is deterministic and collision-free (e.g. include a counter or hash of the query).","Run a quick dedup check: new Set(tasks.map(t => t.id)).size === tasks.length before saving the anchor."],"exampleFix":"// before\n[{\"id\":\"auth\",\"q\":\"...\",\"labels\":[\"x\"]}, {\"id\":\"auth\",\"q\":\"...\",\"labels\":[\"y\"]}]\n// after — make ids unique\n[{\"id\":\"auth-login\",\"q\":\"...\",\"labels\":[\"x\"]}, {\"id\":\"auth-logout\",\"q\":\"...\",\"labels\":[\"y\"]}]","handlingStrategy":"validation","validationCode":"function assertUniqueIds(tasks: { id: string }[]): void {\n  const ids = tasks.map(t => t.id);\n  const dup = ids.find((id, i) => ids.indexOf(id) !== i);\n  if (dup) throw new Error(`duplicate task id detected before load: ${dup}`);\n}","typeGuard":"function hasUniqueIds(tasks: { id: string }[]): boolean {\n  const seen = new Set<string>();\n  for (const t of tasks) {\n    if (seen.has(t.id)) return false;\n    seen.add(t.id);\n  }\n  return true;\n}","tryCatchPattern":"try {\n  loadEffectiveFlywheelAnchor(root, opts);\n} catch (e) {\n  if (e instanceof Error && /duplicate anchor task id: (.+)$/.test(e.message)) {\n    const dupId = e.message.split(': ').pop();\n    // rename the second occurrence of dupId in the anchor, then retry\n  }\n  throw e;\n}","preventionTips":["Run new Set(tasks.map(t => t.id)).size === tasks.length as a pre-commit check.","Make id generators collision-free (include a counter or content hash).","When duplicating a task as a template, always re-id it immediately."],"tags":["flywheel-anchor","validation","uniqueness","json"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}