{"record":{"id":"058a89342589ca50","repo":"tinyhumansai/openhuman","slug":"duplicate-id-agent-id","errorCode":null,"errorMessage":"duplicate id \"${agent.id}\"","messagePattern":"duplicate id \"(.+?)\"","errorType":"validation","errorClass":"SpecError","httpStatus":null,"severity":"error","filePath":"scripts/agent-batch/lib.mjs","lineNumber":104,"sourceCode":"  const seenBranch = new Set();\n  for (let i = 0; i < spec.agents.length; i++) {\n    const agent = spec.agents[i];\n    const at = `agents[${i}]`;\n    if (!agent || typeof agent !== \"object\" || Array.isArray(agent)) {\n      throw new SpecError(\"must be an object\", at);\n    }\n    for (const key of REQUIRED_AGENT) {\n      if (!(key in agent))\n        throw new SpecError(`missing required field \"${key}\"`, at);\n    }\n    if (typeof agent.id !== \"string\" || !/^a\\d{2,3}$/.test(agent.id)) {\n      throw new SpecError(\n        `id must match /^a\\\\d{2,3}$/ (got \"${agent.id}\")`,\n        `${at}.id`,\n      );\n    }\n    if (seenId.has(agent.id))\n      throw new SpecError(`duplicate id \"${agent.id}\"`, `${at}.id`);\n    seenId.add(agent.id);\n    if (!Number.isInteger(agent.issue) || agent.issue <= 0) {\n      throw new SpecError(\"issue must be a positive integer\", `${at}.issue`);\n    }\n    if (seenIssue.has(agent.issue)) {\n      throw new SpecError(`duplicate issue #${agent.issue}`, `${at}.issue`);\n    }\n    seenIssue.add(agent.issue);\n    if (typeof agent.title !== \"string\" || agent.title.trim().length === 0) {\n      throw new SpecError(\"title must be a non-empty string\", `${at}.title`);\n    }\n    const m = BRANCH_RE.exec(agent.branch);\n    if (!m) {\n      throw new SpecError(\n        `branch must match cursor/<id>-<issue>-<slug> (got \"${agent.branch}\")`,\n        `${at}.branch`,\n      );\n    }","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/agent-batch/lib.mjs#L86-L122","documentation":"Agent ids must be unique across the batch; a second agent reusing an id already seen in the seenId Set throws with the duplicated value and path \"agents[i].id\". Ids key branch names and per-agent bookkeeping, so duplicates would alias work units. The error points at the second (offending) occurrence, not the original.","triggerScenarios":"Copy-pasting an agent entry and editing its issue/title but forgetting to bump \"id\": two entries both with \"a03\"; a generator looping over a list with duplicate indices.","commonSituations":"Duplicating an agent as a starting point for a similar task; reordering entries and renumbering only half of them; merge conflicts in the spec JSON resolved by keeping both sides.","solutions":["Renumber the agent reported in the error path to the next unused id (e.g. a03 → a04)","Update that agent's branch id segment to match the new id","Run a quick uniqueness pass: new Set(agents.map(a => a.id)).size === agents.length"],"exampleFix":"// before\n{ \"id\": \"a03\", ... }\n{ \"id\": \"a03\", ... }  // duplicate\n\n// after\n{ \"id\": \"a03\", \"branch\": \"cursor/a03-5314-...\", ... }\n{ \"id\": \"a04\", \"branch\": \"cursor/a04-5315-...\", ... }","handlingStrategy":"validation","validationCode":"const seen = new Set();\nfor (const [i, a] of spec.agents.entries()) {\n  if (seen.has(a.id)) console.error(`duplicate id ${a.id} at agents[${i}]`);\n  seen.add(a.id);\n}","typeGuard":null,"tryCatchPattern":"try {\n  validateSpec(spec);\n} catch (e) {\n  if (e instanceof SpecError && /duplicate id/.test(e.message)) {\n    console.error(`renumber the second occurrence: ${e.message}`);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["After copy-pasting an agent, immediately bump its id, issue, and branch together","Assert uniqueness before validating: new Set(agents.map(a => a.id)).size === agents.length"],"tags":["validation","json","spec","agent-batch","uniqueness"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}