can1357/oh-my-pi · error · Error

resume supports only harbor runs (${jobName} is ${run.benchm

Error message

resume supports only harbor runs (${jobName} is ${run.benchmark})

What it means

resume() re-runs only harbor benchmark runs, because resume replays failed tasks using the recorded harbor config.json and result.json. If the stored run's benchmark is anything else (e.g. 'edit' or 'snapcompact'), there is no harbor config to resume from, so it refuses. The message names both the requested run and its actual benchmark.

Source

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

			note: request.note,
		});
		if (request.goal) this.#store.setExperimentGoal(experimentOf(jobName), request.goal);
		return { jobName, pid };
	}

	/**
	 * Resume a harbor run in place via the runner's `--resume`: completed
	 * trials (and their spend) are reused, interrupted/pending trials re-run,
	 * and errored trials are evicted for retry. The runner recovers the
	 * original launch flags from the run's recorded config, so nothing needs
	 * re-specifying. `filterErrorTypes` overrides the default retry set
	 * (every exception type recorded in the job's result.json).
	 */
	resume(jobName: string, opts: { filterErrorTypes?: string[] } = {}): { jobName: string; pid: number } {
		const run = this.#store.getRun(jobName);
		if (!run) throw new Error(`run ${jobName} not found`);
		if (run.benchmark !== "harbor")
			throw new Error(`resume supports only harbor runs (${jobName} is ${run.benchmark})`);
		// Trust liveness, not the recorded status: a runner killed while a
		// previous server instance owned it leaves a stale `running` row with a
		// dead (or null) pid and nobody to fire markExit.
		if (this.#runLive(run)) {
			throw new Error(`run ${jobName} is already running`);
		}
		if (run.status === "running") this.#store.markExit(jobName, null, true);
		const jobDir = path.join(this.jobsDir, jobName);
		if (!fs.existsSync(path.join(jobDir, "config.json"))) {
			throw new Error(`${jobName} has no harbor config.json to resume from`);
		}
		const argv = ["bun", "src/runner.ts", "--resume", jobName, "--jobs-dir", this.jobsDir];
		for (const t of opts.filterErrorTypes ?? erroredExceptionTypes(jobDir)) argv.push("--filter-error-type", t);
		let prewalk: LaunchRequest["prewalk"];
		try {
			prewalk = run.prewalk ? (JSON.parse(run.prewalk) as { into?: string }) : undefined;
		} catch {
			prewalk = undefined;

View on GitHub (pinned to 9690622007)

Solutions

  1. Only call resume() for runs where run.benchmark === 'harbor'; filter your retry loop accordingly.
  2. For non-harbor benchmarks, relaunch them from scratch with launch() instead of resuming.
  3. Add a pre-call check: if (run.benchmark !== 'harbor') skip or re-launch.
  4. Check store.listRuns() output to confirm which runs are harbor before scripting resumes.

Example fix

// before
for (const r of failedRuns) server.resume(r.jobName);
// after
for (const r of failedRuns) {
  if (r.benchmark === "harbor") server.resume(r.jobName);
  else server.launch({ benchmark: r.benchmark, model: r.model });
}
Defensive patterns

Strategy: type-guard

Validate before calling

const run = store.getRun(jobName);
if (run && run.benchmark !== "harbor") {
  throw new Error(`resume only applies to harbor runs; '${jobName}' is ${run.benchmark}`);
}

Type guard

const isResumable = (r: RunRecord): r is RunRecord & { benchmark: "harbor" } =>
  r.benchmark === "harbor";

Try / catch

try {
  server.resume(jobName);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("resume supports only harbor")) {
    server.launch({ benchmark: run.benchmark, model: run.model }); // relaunch instead
  } else throw err;
}

Prevention

When it happens

Trigger: Calling resume() on a run launched with benchmark 'edit' or 'snapcompact'; a generic retry script that resumes every failed run regardless of benchmark.

Common situations: Batch-retrying all failed runs in the store; assuming resume works universally across benchmark types after it worked for harbor runs.

Related errors


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