{"record":{"id":"b605e7fda7e42f9b","repo":"Yeachan-Heo/oh-my-codex","slug":"invalid-mission-summary-at-summarypath","errorCode":null,"errorMessage":"Invalid mission summary at ${summaryPath}.","messagePattern":"Invalid mission summary at (.+?)\\.","errorType":"validation","errorClass":"MissionCommandError","httpStatus":null,"severity":"error","filePath":"src/cli/mission.ts","lineNumber":296,"sourceCode":"  const summaryPath = parsed.summaryPath\n    ? (isAbsolute(parsed.summaryPath) ? parsed.summaryPath : resolve(cwd, parsed.summaryPath))\n    : join(missionRoot, \"summary.json\");\n  const ledgerPath = join(missionRoot, \"ledger.jsonl\");\n  return { inputPath, slug, missionRoot, summaryPath, ledgerPath };\n}\n\nasync function readSummary(summaryPath: string): Promise<MissionSummary> {\n  let raw: string;\n  try {\n    raw = await readFile(summaryPath, \"utf-8\");\n  } catch {\n    throw new MissionCommandError(`No mission summary found at ${summaryPath}.`);\n  }\n  let summary: MissionSummary;\n  try {\n    summary = JSON.parse(raw) as MissionSummary;\n  } catch {\n    throw new MissionCommandError(`Invalid mission summary at ${summaryPath}.`);\n  }\n  if (summary.version !== 1 || !Array.isArray(summary.tasks)) {\n    throw new MissionCommandError(`Invalid mission summary at ${summaryPath}.`);\n  }\n  return summary;\n}\n\nfunction syncSummary(summary: MissionSummary, updates: Partial<Pick<MissionSummary, \"status\" | \"dry_run\" | \"continue_on_error\" | \"codex_args\">>): void {\n  Object.assign(summary, updates);\n  summary.counts = missionCounts(summary.tasks);\n}\n\nasync function runSelectedTasks(\n  summary: MissionSummary,\n  paths: MissionPaths,\n  parsed: ParsedMissionArgs,\n  now: () => Date,\n  stdout: (line: string) => void,","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/mission.ts#L278-L314","documentation":"readSummary read the file but JSON.parse failed — the summary file is not valid JSON. This indicates a corrupted or hand-edited summary, or a non-summary file at the expected path.","triggerScenarios":"Truncated write (crash during persistSummary), manual editing introducing syntax errors, or a different JSON-incompatible file occupying the summary path.","commonSituations":"Process killed mid-write of the summary; merge conflicts in a committed summary file; editors leaving trailing commas or comments.","solutions":["Re-run the mission to regenerate the summary","Restore the summary from version control","Validate the file with a JSON linter (e.g. jq . summary.json) and fix syntax"],"exampleFix":"# before (broken summary.json)\n{\"version\": 1, \"tasks\": [ ... ],,}\n# after\njq . .mission/summary.json   # find and fix the syntax error, or re-run: mission run mission.md","handlingStrategy":"validation","validationCode":"JSON.parse(await readFile(summaryPath, 'utf-8')); // in try/catch before invoking mission commands","typeGuard":null,"tryCatchPattern":"try { JSON.parse(raw); } catch { /* regenerate summary via mission run before proceeding */ }","preventionTips":["Write summaries atomically (temp file + rename) in your own persistence code","Commit summaries to version control for easy restore"],"tags":["mission","json","corruption"],"backgroundTag":"invalid-json","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}