tinyhumansai/openhuman · error · SpecError

batch size ${spec.agents.length} exceeds hard cap of 25

Error message

batch size ${spec.agents.length} exceeds hard cap of 25

What it means

A hard ceiling: spec.agents.length must not exceed 25. The cap bounds how many concurrent branches/issues/PRs one tracking issue can fan out to, keeping review load and CI cost sane. The actual offending length is interpolated into the message and the path is "agents".

Source

Thrown at scripts/agent-batch/lib.mjs:78

    );
  }
  if (spec.base_branch !== "main") {
    throw new SpecError(
      `base_branch must be "main" (got "${spec.base_branch}")`,
      "base_branch",
    );
  }
  if (!Number.isInteger(spec.tracking_issue) || spec.tracking_issue <= 0) {
    throw new SpecError(
      "tracking_issue must be a positive integer",
      "tracking_issue",
    );
  }
  if (!Array.isArray(spec.agents) || spec.agents.length === 0) {
    throw new SpecError("agents must be a non-empty array", "agents");
  }
  if (spec.agents.length > 25) {
    throw new SpecError(
      `batch size ${spec.agents.length} exceeds hard cap of 25`,
      "agents",
    );
  }

  const seenId = new Set();
  const seenIssue = new Set();
  const seenBranch = new Set();
  for (let i = 0; i < spec.agents.length; i++) {
    const agent = spec.agents[i];
    const at = `agents[${i}]`;
    if (!agent || typeof agent !== "object" || Array.isArray(agent)) {
      throw new SpecError("must be an object", at);
    }
    for (const key of REQUIRED_AGENT) {
      if (!(key in agent))
        throw new SpecError(`missing required field "${key}"`, at);
    }

View on GitHub (pinned to a221052e0d)

Solutions

  1. Split the work into two batches of ≤25 agents, each with its own batch_id slug and its own tracking_issue
  2. Merge trivially small agents so each owns more paths (owned_paths supports multiple directory prefixes)
  3. Re-run validateSpec on each sub-batch spec separately

Example fix

// before: one spec, 30 agents
{ "batch_id": "big-refactor", "agents": [ ...30 entries... ] }

// after: two specs
{ "batch_id": "big-refactor-1", "agents": [ ...first 15... ] }
{ "batch_id": "big-refactor-2", "agents": [ ...next 15... ] }
Defensive patterns

Strategy: validation

Validate before calling

if (spec.agents.length > 25) {
  console.error(`batch size ${spec.agents.length} exceeds hard cap of 25 — split into sub-batches`);
  process.exit(1);
}

Try / catch

try {
  validateSpec(spec);
} catch (e) {
  if (e instanceof SpecError && e.path === "agents" && /hard cap/.test(e.message)) {
    const mid = Math.ceil(spec.agents.length / 2);
    console.error(`split into batches: agents[0..${mid - 1}] and agents[${mid}..]`);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a spec with 26 or more entries in the agents array to validateSpec or the batch launcher.

Common situations: A large mechanical refactor sliced too coarsely (e.g. one agent per domain in the ~31-directory tree plus per-file agents); programmatically generating one agent per item from a long list without chunking.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/56a7ee0583fc764f. Report an issue: GitHub.