can1357/oh-my-pi · error · Error
${jobName} has no harbor config.json to resume from
Error message
${jobName} has no harbor config.json to resume from What it means
ManagerServer throws this when you ask it to resume a harbor job whose job directory contains no config.json. Resume works by re-spawning `runner.ts --resume <jobName> --jobs-dir <jobsDir>`, which requires the original harbor config persisted in `<jobsDir>/<jobName>/config.json`; without it the runner has nothing to resume from. The server treats a missing config as a caller/state error rather than silently failing inside the child.
Source
Thrown at packages/metaharness/src/server.ts:456
* 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;
}
const pid = this.#spawnRunner(argv, PKG_DIR, {
benchmark: "harbor",
jobName,
dataset: run.dataset,
agent: run.agent,
models: run.models ? run.models.split(",") : [],
prewalk,
config: run.config,
role: run.role,View on GitHub (pinned to 9690622007)
Solutions
- Verify the job directory exists and contains config.json: `ls <jobsDir>/<jobName>/config.json`
- If the directory is gone, relaunch the job from scratch instead of resuming
- If the jobsDir is wrong, restart the manager with the correct --jobs-dir path
- If the job name is mistyped, list available jobs (`ls <jobsDir>`) and use the exact name
Example fix
// before
await server.resumeRun("job-42"); // throws: job-42 has no harbor config.json
// after
const jobDir = path.join(jobsDir, "job-42");
if (!fs.existsSync(path.join(jobDir, "config.json"))) {
await server.launchRun("job-42"); // fresh launch instead of resume
} else {
await server.resumeRun("job-42");
} Defensive patterns
Strategy: validation
Validate before calling
import * as fs from "node:fs";
import * as path from "node:path";
function canResume(jobsDir: string, jobName: string): boolean {
return fs.existsSync(path.join(jobsDir, jobName, "config.json"));
} Try / catch
try {
server.resumeRun(jobName);
} catch (err) {
if (err instanceof Error && err.message.includes("has no harbor config.json")) {
server.launchRun(jobName); // fall back to a fresh launch
} else throw err;
} Prevention
- Check config.json exists before calling resume
- Never manually delete files under jobsDir
- Use the exact jobName from the manager's run listing
- Point the manager at the same --jobs-dir used for the original launch
When it happens
Trigger: Calling the resume API (e.g. `resumeRun`/`launchRun` with resume semantics, or the corresponding RPC) for a jobName whose `jobsDir/<jobName>/config.json` does not exist — e.g. resuming a job that was never launched, after the job dir was deleted, or with a typo'd job name.
Common situations: Manual cleanup deleted parts of the jobs directory; the job was created in a different jobsDir and you pointed the server at the wrong `--jobs-dir`; typo in jobName; attempting to resume a job that only got as far as a DB row before config.json was written.
Related errors
- unknown filetype: {ft_debug}
- Is a directory
- Too many levels of symbolic links
- {}: {error}
- directory stack is empty
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/409056e1f474dde9.
Report an issue: GitHub.