{"record":{"id":"c585c0c44e970cdb","repo":"shareAI-lab/learn-claude-code","slug":"invalid-resume-snapshot-for-run-id","errorCode":null,"errorMessage":"invalid resume snapshot for {run_id}","messagePattern":"invalid resume snapshot for (.+?)","errorType":"validation","errorClass":"WorkflowInputError","httpStatus":null,"severity":"error","filePath":"s16_workflow_runtime/code.py","lineNumber":627,"sourceCode":"                   outputFile=f\".runtime/{run_id}.output.json\")\n        return {\"launched\": launched, \"result\": result, \"task\": task}\n\n\ndef _write_json(path, value):\n    path.parent.mkdir(parents=True, exist_ok=True)\n    temporary = path.with_suffix(path.suffix + \".tmp\")\n    temporary.write_text(json.dumps(value, indent=2, default=str))\n    os.replace(temporary, path)\n\n\ndef _read_snapshot(run_id):\n    path = STORE / f\"{run_id}.json\"\n    if not path.exists():\n        raise WorkflowInputError(f\"resume snapshot not found for {run_id}\")\n    try:\n        snapshot = json.loads(path.read_text())\n    except json.JSONDecodeError as exc:\n        raise WorkflowInputError(f\"invalid resume snapshot for {run_id}\") from exc\n    if not isinstance(snapshot, dict):\n        raise WorkflowInputError(f\"invalid resume snapshot for {run_id}\")\n    return snapshot\n\n\ndef _save_last_run(run_id):\n    (STORE / \"last_run.txt\").write_text(run_id)\n\n\ndef _read_last_run():\n    p = STORE / \"last_run.txt\"\n    return p.read_text().strip() if p.exists() else None\n\n\n# -- Sample Workflow --\nFINDINGS_SCHEMA = {\n    \"type\": \"object\", \"required\": [\"findings\"],\n    \"properties\": {\"findings\": {\"type\": \"array\", \"items\": {","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s16_workflow_runtime/code.py#L609-L645","documentation":"The first 'invalid resume snapshot' variant: STORE/<run_id>.json exists but json.loads() raises JSONDecodeError, so _read_snapshot re-raises it as WorkflowInputError('invalid resume snapshot for <run_id>'). The snapshot is written atomically via a .tmp file and os.replace, so corruption almost always means external interference rather than a torn write.","triggerScenarios":"Resuming a run whose snapshot file has been truncated or mangled — crashed disk, hand-editing, a tool writing into .runtime, or encoding damage.","commonSituations":"Manual edits to .runtime JSON; partial file after an out-of-space event despite atomic replace of an earlier bad write; merge conflicts when the directory is checked into version control.","solutions":["Inspect STORE/<run_id>.json with a JSON linter to find the syntax error (commonly a trailing comma or truncated tail).","Restore the snapshot from backup or a synced copy if the run must be resumed.","If unrecoverable, delete the snapshot and start a fresh run (accepting full re-execution cost)."],"exampleFix":"# before: snapshot truncated to '{\"workflowName\": \"review\", \"args\":'\n# after: repair to valid JSON\n{\"workflowName\": \"review\", \"args\": {\"changes\": \"...\"}}","handlingStrategy":"validation","validationCode":"import json\nfrom s16_workflow_runtime import STORE\ndef snapshot_parses(run_id: str) -> bool:\n    try:\n        json.loads((STORE / f\"{run_id}.json\").read_text())\n        return True\n    except (OSError, json.JSONDecodeError):\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    await run_workflow(name, resume_from_run_id=rid)\nexcept WorkflowInputError as e:\n    if \"invalid resume snapshot\" in str(e):\n        repair_or_backup_snapshot(STORE / f\"{rid}.json\")  # then decide: resume vs fresh run\n    raise","preventionTips":["Never hand-edit snapshot JSON; if you must, validate with json.tool afterwards.","Exclude .runtime from formatters/linters and version control that could rewrite files.","Keep backups of .runtime before risky maintenance so resumes stay possible."],"tags":["workflow","resume","snapshot","json","corruption"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}