can1357/oh-my-pi · error · Error

--resume: ${jobDir} has no harbor config.json (not a harbor

Error message

--resume: ${jobDir} has no harbor config.json (not a harbor job dir)

What it means

resolveResumeConfig reconstructs a Config from a previous job directory. It first reads <jobDir>/config.json to verify the directory actually is a harbor job dir; if the file is missing or unparseable (readJson returns null), it throws rather than guessing, because all subsequent reconstruction depends on that config.

Source

Thrown at packages/metaharness/src/runner.ts:397

	dataset?: string;
	config?: LaunchRequest;
}

/**
 * Recover the original launch Config for `--resume <job>` — nothing needs
 * re-specifying. Prefers the exact Config snapshot recorded at launch
 * (`_bench/<job>/runner-config.json`), falling back to rebuilding runner argv
 * from the manager.json launch record of API-launched runs. The job dir's own
 * harbor config.json decides the container backend: harbor rejects a resume
 * whose reconstructed config differs from the recorded one.
 */
export function resolveResumeConfig(cli: Config): Config {
	const spec = cli.resume as string;
	const jobsDir = spec.includes(path.sep) ? path.dirname(path.resolve(spec)) : cli.jobsDir;
	const jobName = path.basename(spec);
	const jobDir = path.join(jobsDir, jobName);
	const jobConfig = readJson(path.join(jobDir, "config.json")) as { environment?: { type?: string } } | null;
	if (!jobConfig) throw new Error(`--resume: ${jobDir} has no harbor config.json (not a harbor job dir)`);

	let cfg: Config | null = null;
	const saved = readJson(path.join(jobsDir, "_bench", jobName, "runner-config.json"));
	if (saved && typeof saved === "object") {
		cfg = { ...defaultConfig(), ...(saved as Partial<Config>) };
	} else {
		const manager = readJson(path.join(jobDir, "manager.json")) as ManagerRecord | null;
		if (manager?.config) {
			if (manager.benchmark && manager.benchmark !== "harbor") {
				throw new Error(`--resume supports only harbor runs (${jobName} is ${manager.benchmark})`);
			}
			const dataset = manager.config.dataset ?? manager.dataset ?? "terminal-bench@2.0";
			cfg = parseArgs(harborRunnerArgs(manager.config, { jobsDir, jobName, dataset }));
		}
	}
	if (!cfg) {
		throw new Error(
			`--resume: no recorded launch config for ${jobName} ` +

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the directory exists and contains config.json: `ls <jobsDir>/<jobName>/config.json`.
  2. Use --resume with just the job name (resolved under --jobs-dir) or a full path to the job dir — mixed forms resolve differently (path separator triggers dirname resolution).
  3. Recreate the job if config.json was deleted; resume cannot proceed without it.
  4. Point --jobs-dir at the directory that actually contains your job dirs.

Example fix

// before
runner --resume myjob   # jobs dir default, job actually in /tmp/runs/myjob
// after
runner --resume /tmp/runs/myjob   # or: runner --jobs-dir /tmp/runs --resume myjob
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "node:fs";
const jobDir = spec.includes(path.sep) ? path.dirname(path.resolve(spec)) : path.join(jobsDir, spec);
if (!fs.existsSync(path.join(jobDir, "config.json"))) {
  throw new Error(`not a harbor job dir (no config.json): ${jobDir}`);
}

Type guard

function isJobDir(p: string): boolean {
  return fs.existsSync(path.join(p, "config.json"));
}

Try / catch

try {
  await resumeJob(spec);
} catch (e) {
  if (e instanceof Error && e.message.includes("has no harbor config.json")) {
    console.error(`No harbor job at '${spec}'. Check job name and --jobs-dir.`);
  } else throw e;
}

Prevention

When it happens

Trigger: `runner --resume <name>` where <jobsDir>/<name>/config.json does not exist; --resume given a path whose parent dir is the wrong folder; the job dir was partially deleted or cleanup removed config.json; typo'd job name so the dir itself doesn't exist.

Common situations: Resuming after manually clearing the job directory; passing a job from a different benchmark tool that has no harbor config.json; running from the wrong cwd so cli.jobsDir points elsewhere; truncation of the spec path.

Related errors


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