can1357/oh-my-pi · error · Error

arm '${req.arm}' already exists in '${experimentId}'

Error message

arm '${req.arm}' already exists in '${experimentId}'

What it means

Each arm's job name is `<experimentId>-<arm>`, and the run store enforces uniqueness via store.getRun(jobName). This error means a run with that exact job name already exists, i.e. an arm with this name has already been added to the experiment. Arms are immutable labels — re-adding would collide with the existing run's directory and records.

Source

Thrown at packages/metaharness/src/server.ts:164

	// Exact task sample: prefer the intended include list, else observed trial
	// tasks. Trial task names are stored bare, while org-prefixed datasets
	// (e.g. "swe-bench/swe-bench-verified") address tasks as "<org>/<task>" —
	// re-derive the prefix for the fallback.
	let include = req.include && req.include.length > 0 ? req.include : strings(cfg.include);
	if (include.length === 0) {
		const org = template.dataset.includes("/") ? `${template.dataset.split("/", 1)[0]}/` : "";
		include = [
			...new Set(
				store
					.listTraces(template.jobName)
					.map(t => t.task)
					.filter(Boolean)
					.map(task => (task.includes("/") ? task : `${org}${task}`)),
			),
		];
	}
	const jobName = `${experimentId}-${req.arm}`;
	if (store.getRun(jobName)) throw new Error(`arm '${req.arm}' already exists in '${experimentId}'`);
	const conditions = strings(cfg.conditions);
	return {
		benchmark: template.benchmark,
		model: req.model,
		dataset: template.dataset,
		include: include.length > 0 ? include : undefined,
		tasks: include.length > 0 ? include.length : numberOr(cfg.tasks),
		concurrency: numberOr(cfg.concurrency),
		timeoutMultiplier: numberOr(cfg.timeoutMultiplier),
		attempts: numberOr(cfg.attempts),
		agent: str(cfg.agent),
		webSearch: cfg.webSearch === true || undefined,
		prebuiltBinaries: cfg.prebuiltBinaries === true || undefined,
		conditions: conditions.length > 0 ? conditions : undefined,
		jobName,
		prewalk: req.prewalk,
		role: req.role,
		note: req.note,

View on GitHub (pinned to 9690622007)

Solutions

  1. Use a new, unique arm name (e.g. append a version suffix: 'baseline-v2').
  2. Check existing runs first and skip the call if store.getRun(`${experimentId}-${arm}`) returns a run.
  3. If the old arm's run is stale/unwanted and the API supports it, remove or archive that run before re-adding.
  4. Make batch scripts idempotent by filtering out arm names already present in the store.

Example fix

// before
server.addArm("myexp", { arm: "baseline", model: "m2" }); // second call
// after
const arm = existing.has("myexp-baseline") ? "baseline-v2" : "baseline";
server.addArm("myexp", { arm, model: "m2" });
Defensive patterns

Strategy: validation

Validate before calling

const jobName = `${experimentId}-${req.arm}`;
if (store.getRun(jobName)) {
  console.warn(`arm '${req.arm}' already present; skipping`);
  return;
}

Try / catch

try {
  server.addArm(expId, req);
} catch (err) {
  if (err instanceof Error && err.message.includes("already exists")) {
    req.arm = `${req.arm}-${Date.now().toString(36)}`;
    server.addArm(expId, req);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling addArm twice with the same arm name for the same experiment; re-running an idempotent-looking script that previously created the arm; a previous failed launch that still registered the run.

Common situations: Replaying a bootstrap script after partial failure; copy-pasting addArm calls with identical arm names; wanting to re-run an arm with a new model but reusing its old name.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/42b063d161e413b3. Report an issue: GitHub.