{"record":{"id":"aec0c65667b2173a","repo":"can1357/oh-my-pi","slug":"resume-no-recorded-launch-config-for-jobname","errorCode":null,"errorMessage":"--resume: no recorded launch config for ${jobName} (missing both _bench/${jobName}/runner-config.json and ${jobName}/manager.json)","messagePattern":"--resume: no recorded launch config for (.+?) \\(missing both _bench/(.+?)/runner-config\\.json and (.+?)/manager\\.json\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/metaharness/src/runner.ts","lineNumber":414,"sourceCode":"\tconst jobConfig = readJson(path.join(jobDir, \"config.json\")) as { environment?: { type?: string } } | null;\n\tif (!jobConfig) throw new Error(`--resume: ${jobDir} has no harbor config.json (not a harbor job dir)`);\n\n\tlet cfg: Config | null = null;\n\tconst saved = readJson(path.join(jobsDir, \"_bench\", jobName, \"runner-config.json\"));\n\tif (saved && typeof saved === \"object\") {\n\t\tcfg = { ...defaultConfig(), ...(saved as Partial<Config>) };\n\t} else {\n\t\tconst manager = readJson(path.join(jobDir, \"manager.json\")) as ManagerRecord | null;\n\t\tif (manager?.config) {\n\t\t\tif (manager.benchmark && manager.benchmark !== \"harbor\") {\n\t\t\t\tthrow new Error(`--resume supports only harbor runs (${jobName} is ${manager.benchmark})`);\n\t\t\t}\n\t\t\tconst dataset = manager.config.dataset ?? manager.dataset ?? \"terminal-bench@2.0\";\n\t\t\tcfg = parseArgs(harborRunnerArgs(manager.config, { jobsDir, jobName, dataset }));\n\t\t}\n\t}\n\tif (!cfg) {\n\t\tthrow new Error(\n\t\t\t`--resume: no recorded launch config for ${jobName} ` +\n\t\t\t\t`(missing both _bench/${jobName}/runner-config.json and ${jobName}/manager.json)`,\n\t\t);\n\t}\n\tcfg.jobsDir = jobsDir;\n\tcfg.jobName = jobName;\n\tcfg.resume = spec;\n\t// The recorded backend wins over any reconstruction-time preference\n\t// (e.g. apple-container auto-detection added after the original run).\n\tconst recorded = jobConfig.environment?.type;\n\tif ((recorded === \"docker\" || recorded === \"apple-container\") && cfg.envType !== recorded) {\n\t\tif (recorded === \"apple-container\" && cfg.gatewayUrl === DOCKER_GATEWAY_URL) cfg.gatewayUrl = VMNET_GATEWAY_URL;\n\t\telse if (recorded === \"docker\" && cfg.gatewayUrl === VMNET_GATEWAY_URL) cfg.gatewayUrl = DOCKER_GATEWAY_URL;\n\t\tcfg.envType = recorded;\n\t}\n\t// Knobs owned by the resume invocation, not the original launch.\n\tcfg.filterErrorTypes = cli.filterErrorTypes;\n\tcfg.passthrough = cli.passthrough;","sourceCodeStart":396,"sourceCodeEnd":432,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/metaharness/src/runner.ts#L396-L432","documentation":"Resume requires a recorded launch config from one of two sources: the saved _bench/<jobName>/runner-config.json, or <jobDir>/manager.json (from which args are re-derived). If both are absent/unreadable, there is nothing to reconstruct the run from, so the error names both candidate paths explicitly.","triggerScenarios":"Job dir exists and has config.json, but the _bench metadata dir was cleaned up AND manager.json is missing; resuming a job created by an older runner version that wrote neither file; manually copying a job dir without its metadata.","commonSituations":"Jobs dirs pruned by a cleanup script that keeps config.json but drops _bench; sharing a single job dir between machines; interrupted first launch that crashed before writing any launch record.","solutions":["Check both files exist: `cat <jobsDir>/_bench/<job>/runner-config.json` and `<jobsDir>/<job>/manager.json`.","Re-run the job from scratch instead of resuming — there is no launch config to recover.","Restore the missing file from backup or re-copy the complete job dir including _bench/.","Upgrade: if older runner versions didn't persist these, re-run once with a current version so future resumes work."],"exampleFix":"// before\nrunner --resume jobA   # jobA/config.json exists but no _bench/jobA/runner-config.json, no jobA/manager.json\n// after\nrunner --resume jobA   # after restoring _bench/jobA/runner-config.json from backup","handlingStrategy":"validation","validationCode":"import * as fs from \"node:fs\";\nconst hasSaved = fs.existsSync(path.join(jobsDir, \"_bench\", jobName, \"runner-config.json\"));\nconst hasManager = fs.existsSync(path.join(jobDir, \"manager.json\"));\nif (!hasSaved && !hasManager) {\n  throw new Error(`no launch config to resume from for '${jobName}' — rerun from scratch`);\n}","typeGuard":"function isResumable(jobsDir: string, jobName: string): boolean {\n  return fs.existsSync(path.join(jobsDir, \"_bench\", jobName, \"runner-config.json\")) ||\n         fs.existsSync(path.join(jobsDir, jobName, \"manager.json\"));\n}","tryCatchPattern":"try {\n  await resumeJob(name);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"no recorded launch config\")) {\n    console.error(\"No runner-config.json or manager.json found — the job must be re-run, not resumed.\");\n  } else throw e;\n}","preventionTips":["Copy whole job dirs (including _bench/) when archiving or sharing.","Exclude _bench/ and manager.json from cleanup scripts.","After a fresh runner upgrade, re-run jobs once so launch configs are recorded in the new format."],"tags":["resume","missing-file","job-directory"],"backgroundTag":"missing-job-config","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}