{"record":{"id":"e3ca35494fdff466","repo":"can1357/oh-my-pi","slug":"resume-supports-only-harbor-runs-jobname-is-e3ca35","errorCode":null,"errorMessage":"resume supports only harbor runs (${jobName} is ${run.benchmark})","messagePattern":"resume supports only harbor runs \\((.+?) is (.+?)\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/metaharness/src/server.ts","lineNumber":446,"sourceCode":"\t\t\tnote: request.note,\n\t\t});\n\t\tif (request.goal) this.#store.setExperimentGoal(experimentOf(jobName), request.goal);\n\t\treturn { jobName, pid };\n\t}\n\n\t/**\n\t * Resume a harbor run in place via the runner's `--resume`: completed\n\t * trials (and their spend) are reused, interrupted/pending trials re-run,\n\t * and errored trials are evicted for retry. The runner recovers the\n\t * original launch flags from the run's recorded config, so nothing needs\n\t * re-specifying. `filterErrorTypes` overrides the default retry set\n\t * (every exception type recorded in the job's result.json).\n\t */\n\tresume(jobName: string, opts: { filterErrorTypes?: string[] } = {}): { jobName: string; pid: number } {\n\t\tconst run = this.#store.getRun(jobName);\n\t\tif (!run) throw new Error(`run ${jobName} not found`);\n\t\tif (run.benchmark !== \"harbor\")\n\t\t\tthrow new Error(`resume supports only harbor runs (${jobName} is ${run.benchmark})`);\n\t\t// Trust liveness, not the recorded status: a runner killed while a\n\t\t// previous server instance owned it leaves a stale `running` row with a\n\t\t// dead (or null) pid and nobody to fire markExit.\n\t\tif (this.#runLive(run)) {\n\t\t\tthrow new Error(`run ${jobName} is already running`);\n\t\t}\n\t\tif (run.status === \"running\") this.#store.markExit(jobName, null, true);\n\t\tconst jobDir = path.join(this.jobsDir, jobName);\n\t\tif (!fs.existsSync(path.join(jobDir, \"config.json\"))) {\n\t\t\tthrow new Error(`${jobName} has no harbor config.json to resume from`);\n\t\t}\n\t\tconst argv = [\"bun\", \"src/runner.ts\", \"--resume\", jobName, \"--jobs-dir\", this.jobsDir];\n\t\tfor (const t of opts.filterErrorTypes ?? erroredExceptionTypes(jobDir)) argv.push(\"--filter-error-type\", t);\n\t\tlet prewalk: LaunchRequest[\"prewalk\"];\n\t\ttry {\n\t\t\tprewalk = run.prewalk ? (JSON.parse(run.prewalk) as { into?: string }) : undefined;\n\t\t} catch {\n\t\t\tprewalk = undefined;","sourceCodeStart":428,"sourceCodeEnd":464,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/metaharness/src/server.ts#L428-L464","documentation":"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.","triggerScenarios":"Calling resume() on a run launched with benchmark 'edit' or 'snapcompact'; a generic retry script that resumes every failed run regardless of benchmark.","commonSituations":"Batch-retrying all failed runs in the store; assuming resume works universally across benchmark types after it worked for harbor runs.","solutions":["Only call resume() for runs where run.benchmark === 'harbor'; filter your retry loop accordingly.","For non-harbor benchmarks, relaunch them from scratch with launch() instead of resuming.","Add a pre-call check: if (run.benchmark !== 'harbor') skip or re-launch.","Check store.listRuns() output to confirm which runs are harbor before scripting resumes."],"exampleFix":"// before\nfor (const r of failedRuns) server.resume(r.jobName);\n// after\nfor (const r of failedRuns) {\n  if (r.benchmark === \"harbor\") server.resume(r.jobName);\n  else server.launch({ benchmark: r.benchmark, model: r.model });\n}","handlingStrategy":"type-guard","validationCode":"const run = store.getRun(jobName);\nif (run && run.benchmark !== \"harbor\") {\n  throw new Error(`resume only applies to harbor runs; '${jobName}' is ${run.benchmark}`);\n}","typeGuard":"const isResumable = (r: RunRecord): r is RunRecord & { benchmark: \"harbor\" } =>\n  r.benchmark === \"harbor\";","tryCatchPattern":"try {\n  server.resume(jobName);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"resume supports only harbor\")) {\n    server.launch({ benchmark: run.benchmark, model: run.model }); // relaunch instead\n  } else throw err;\n}","preventionTips":["Filter retry loops to run.benchmark === 'harbor' before calling resume().","Route edit/snapcompact failures to a relaunch path, not resume.","Encode resumability in your retry-policy config per benchmark type.","Read the run record before any automated resume."],"tags":["unsupported-operation","benchmark-type","validation"],"backgroundTag":"operation-unsupported-for-type","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}