tinyhumansai/openhuman · error · SpecError

base_repo must be "tinyhumansai/openhuman" (got "${spec.base

Error message

base_repo must be "tinyhumansai/openhuman" (got "${spec.base_repo}")

What it means

validateSpec() hard-pins the top-level base_repo to exactly "tinyhumansai/openhuman"; any other value (or non-string) throws. The batch tooling is only sanctioned to fork/branch from the upstream repository, so forks, mirrors, or renamed remotes are rejected outright. The offending value is interpolated into the message so the diff from the expected literal is visible.

Source

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

// Validate a parsed spec. Returns the spec on success, throws SpecError on
// any policy violation. The caller is responsible for printing.
export function validateSpec(spec) {
  if (!spec || typeof spec !== "object" || Array.isArray(spec)) {
    throw new SpecError("spec must be a JSON object");
  }
  for (const key of REQUIRED_TOP) {
    if (!(key in spec))
      throw new SpecError(`missing required top-level field "${key}"`);
  }
  if (
    typeof spec.batch_id !== "string" ||
    !/^[a-z0-9][a-z0-9-]*$/.test(spec.batch_id)
  ) {
    throw new SpecError("batch_id must be a kebab-case slug", "batch_id");
  }
  if (spec.base_repo !== "tinyhumansai/openhuman") {
    throw new SpecError(
      `base_repo must be "tinyhumansai/openhuman" (got "${spec.base_repo}")`,
      "base_repo",
    );
  }
  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");

View on GitHub (pinned to a221052e0d)

Solutions

  1. Set base_repo to the literal "tinyhumansai/openhuman"
  2. If you intended to run against a fork, note the tool refuses this by design — re-point the spec at upstream and branch from upstream/main
  3. Check for stray whitespace or case differences in the JSON value

Example fix

// before
"base_repo": "myfork/openhuman"

// after
"base_repo": "tinyhumansai/openhuman"
Defensive patterns

Strategy: validation

Validate before calling

if (spec.base_repo !== "tinyhumansai/openhuman") {
  console.error(`base_repo must be tinyhumansai/openhuman, got ${spec.base_repo}`);
  process.exit(1);
}

Type guard

/** @param {unknown} v */
function isUpstreamRepo(v) {
  return v === "tinyhumansai/openhuman";
}

Try / catch

try {
  validateSpec(spec);
} catch (e) {
  if (e instanceof SpecError && e.path === "base_repo") {
    // point the operator at the spec file, not the tool
    console.error(`fix ${specPath}: ${e.message}`);
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Running validateSpec on a spec with "base_repo": "yourname/openhuman" (a fork), "base_repo": "tinyhumansai/opencompany" (wrong product), a missing-but-present null, or a repo string with different case such as "TinyHumansAI/OpenHuman".

Common situations: An operator templating a spec from their own fork checkout; a copy-paste from another TinyHumans repo's batch spec; case-normalization by an editor or YAML-to-JSON converter.

Related errors


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