tinyhumansai/openhuman · error · SpecError
duplicate issue #${agent.issue}
Error message
duplicate issue #${agent.issue} What it means
Each agent must own a distinct GitHub issue; a second agent reusing an issue number already in the seenIssue Set throws with the number and path "agents[i].issue". The design is one-issue-per-agent so PR descriptions, status, and completion can be tracked per agent without ambiguity.
Source
Thrown at scripts/agent-batch/lib.mjs:110
}
for (const key of REQUIRED_AGENT) {
if (!(key in agent))
throw new SpecError(`missing required field "${key}"`, at);
}
if (typeof agent.id !== "string" || !/^a\d{2,3}$/.test(agent.id)) {
throw new SpecError(
`id must match /^a\\d{2,3}$/ (got "${agent.id}")`,
`${at}.id`,
);
}
if (seenId.has(agent.id))
throw new SpecError(`duplicate id "${agent.id}"`, `${at}.id`);
seenId.add(agent.id);
if (!Number.isInteger(agent.issue) || agent.issue <= 0) {
throw new SpecError("issue must be a positive integer", `${at}.issue`);
}
if (seenIssue.has(agent.issue)) {
throw new SpecError(`duplicate issue #${agent.issue}`, `${at}.issue`);
}
seenIssue.add(agent.issue);
if (typeof agent.title !== "string" || agent.title.trim().length === 0) {
throw new SpecError("title must be a non-empty string", `${at}.title`);
}
const m = BRANCH_RE.exec(agent.branch);
if (!m) {
throw new SpecError(
`branch must match cursor/<id>-<issue>-<slug> (got "${agent.branch}")`,
`${at}.branch`,
);
}
if (m[1] !== agent.id) {
throw new SpecError(
`branch id segment "${m[1]}" does not match agent id "${agent.id}"`,
`${at}.branch`,
);
}View on GitHub (pinned to a221052e0d)
Solutions
- Open a separate GitHub issue for the second agent and update its issue field
- If the work truly is one issue, merge the two agents into one entry with combined owned_paths
- Verify uniqueness: new Set(agents.map(a => a.issue)).size === agents.length
Example fix
// before
{ "id": "a01", "issue": 5312, ... }
{ "id": "a02", "issue": 5312, ... }
// after
{ "id": "a01", "issue": 5312, ... }
{ "id": "a02", "issue": 5313, "branch": "cursor/a02-5313-...", ... } Defensive patterns
Strategy: validation
Validate before calling
const issues = spec.agents.map((a) => a.issue);
if (new Set(issues).size !== issues.length) {
console.error("each agent needs its own issue number");
process.exit(1);
} Try / catch
try {
validateSpec(spec);
} catch (e) {
if (e instanceof SpecError && /duplicate issue/.test(e.message)) {
console.error(`split the work or open a new issue: ${e.message}`);
process.exit(1);
}
throw e;
} Prevention
- Treat one-issue-per-agent as a planning rule, not just a validation rule — split issues on GitHub before speccing
- Generate the spec from your issue list so numbers come straight from the source
When it happens
Trigger: Two agent entries both carrying "issue": 5312; a generator assigning the tracking_issue number to every agent; splitting one issue's work across two agents while keeping the same issue field.
Common situations: Copying an agent entry and forgetting to update issue; deciding mid-spec that two agents share one issue — the schema forbids it, so the issue must be split upstream on GitHub first.
Related errors
- tracking_issue must be a positive integer
- duplicate id "${agent.id}"
- issue must be a positive integer
- branch issue segment "${m[2]}" does not match agent issue ${
- duplicate branch "${agent.branch}"
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/a04193780d18ac01.
Report an issue: GitHub.