{"record":{"id":"d6fa1a2f0ba0d693","repo":"tinyhumansai/openhuman","slug":"id-must-match-a-d-2-3-got-agent-id","errorCode":null,"errorMessage":"id must match /^a\\\\d{2,3}$/ (got \"${agent.id}\")","messagePattern":"id must match /\\^a\\\\\\\\d(.+?)\\$/ \\(got \"(.+?)\"\\)","errorType":"validation","errorClass":"SpecError","httpStatus":null,"severity":"error","filePath":"scripts/agent-batch/lib.mjs","lineNumber":98,"sourceCode":"      \"agents\",\n    );\n  }\n\n  const seenId = new Set();\n  const seenIssue = new Set();\n  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);","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/agent-batch/lib.mjs#L80-L116","documentation":"agent.id must be a string matching /^a\\d{2,3}$/ — the literal letter 'a' followed by exactly 2 or 3 digits (\"a01\" through \"a999\"). The id encodes agent ordering and appears in branch names (enforced later by BRANCH_RE), so the format is strict. The offending value is shown in the message with path \"agents[i].id\".","triggerScenarios":"\"id\": \"a1\" (one digit), \"a1234\" (four digits), \"A01\" (uppercase), \"agent01\", \"01\", or a non-string id like 1.","commonSituations":"Numbering agents from 1 without zero-padding (\"a1\"); exceeding 999 agents in numbering scheme; auto-uppercasing editors; using \"agent01\" style from a different convention.","solutions":["Zero-pad to two digits: a1 → a01 (three digits a100+ also valid)","Keep it lowercase with no prefix/suffix beyond the digits","If renumbering, also update the branch's id segment to match (error 194 will otherwise fire next)"],"exampleFix":"// before\n{ \"id\": \"a1\", \"branch\": \"cursor/a1-5312-fix-ci\" }\n\n// after\n{ \"id\": \"a01\", \"branch\": \"cursor/a01-5312-fix-ci\" }","handlingStrategy":"validation","validationCode":"for (const [i, a] of spec.agents.entries()) {\n  if (typeof a.id !== \"string\" || !/^a\\d{2,3}$/.test(a.id)) {\n    console.error(`agents[${i}].id must match /^a\\\\d{2,3}$/ (got ${JSON.stringify(a.id)})`);\n    process.exit(1);\n  }\n}","typeGuard":"/** @param {unknown} v */\nfunction isAgentId(v) {\n  return typeof v === \"string\" && /^a\\d{2,3}$/.test(v);\n}","tryCatchPattern":"try {\n  validateSpec(spec);\n} catch (e) {\n  if (e instanceof SpecError && e.path?.endsWith(\".id\")) {\n    console.error(`agent id format bad: ${e.message}`);\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Zero-pad ids to two digits from the start (a01, a02, ...)","Generate ids programmatically: `a${String(i + 1).padStart(2, \"0\")}`","Remember the same id appears in the branch name — change both together"],"tags":["validation","json","spec","agent-batch","naming"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}