{"record":{"id":"f7887fef86c1c5ba","repo":"shareAI-lab/learn-claude-code","slug":"resume-runid-does-not-match-workflow-meta","errorCode":null,"errorMessage":"resume runId does not match workflow meta","messagePattern":"resume runId does not match workflow meta","errorType":"validation","errorClass":"WorkflowInputError","httpStatus":null,"severity":"error","filePath":"s16_workflow_runtime/code.py","lineNumber":559,"sourceCode":"\n    async def call(self, meta, script_fn, args=None, resume_from_run_id=None):\n        validate_meta(meta)\n        check_permission(meta)\n        resuming = resume_from_run_id is not None\n        if resuming:\n            run_id = validate_run_id(resume_from_run_id)\n        else:\n            run_id = reserve_run_id(meta)\n        with workflow_run_lock(run_id):\n            return await self._call_locked(\n                meta, script_fn, args, run_id, resuming\n            )\n\n    async def _call_locked(self, meta, script_fn, args, run_id, resuming):\n        if resuming:\n            snapshot = _read_snapshot(run_id)\n            if snapshot.get(\"workflowName\") != meta[\"name\"]:\n                raise WorkflowInputError(\"resume runId does not match workflow meta\")\n            saved_args = snapshot.get(\"args\", {})\n            if args is None:\n                args = saved_args\n            elif args != saved_args:\n                raise WorkflowInputError(\"resume args do not match the original run\")\n            journal = WorkflowJournal(run_id, resume=True)\n        else:\n            args = args or {}\n            journal = WorkflowJournal(run_id, resume=False)\n        task_id = create_task_id(run_id)\n\n        task = LocalWorkflowTask(task_id, run_id, meta)\n        # Record the launch envelope before workflow execution starts.\n        launched = {\"status\": \"async_launched\", \"taskId\": task_id,\n                    \"taskType\": \"local_workflow\", \"runId\": run_id,\n                    \"workflowName\": meta[\"name\"]}\n        task.event(\"async_launched\", runId=run_id, taskId=task_id)\n        task.event(\"task_started\", workflow=meta[\"name\"],","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s16_workflow_runtime/code.py#L541-L577","documentation":"When WorkflowTool.call() is invoked with resume_from_run_id, _call_locked() reads the persisted snapshot for that runId and verifies snapshot['workflowName'] equals the meta['name'] of the workflow being executed. A mismatch raises WorkflowInputError('resume runId does not match workflow meta'), preventing a runId from being replayed against a different workflow's code and journal keys.","triggerScenarios":"run_workflow(name='A', resume_from_run_id=<runId originally created for workflow 'B'>), including runIds whose wf_<name>_... prefix names a different workflow.","commonSituations":"Copy-pasting a runId from logs of another workflow; renaming a workflow after a run was launched; UI passing the last runId regardless of which workflow produced it.","solutions":["Resume with the same workflow name that created the run (the runId's wf_<name>_ prefix tells you which).","If the workflow was renamed, resume under its old name or start a fresh run under the new name.","Inspect STORE/<run_id>.json's workflowName field to confirm which workflow owns the snapshot."],"exampleFix":"# before\nawait run_workflow(\"security-review\", resume_from_run_id=\"wf_codegen_abc...123\")\n\n# after\n# runId prefix says the snapshot belongs to \"codegen\"\nawait run_workflow(\"codegen\", resume_from_run_id=\"wf_codegen_abc...123\")","handlingStrategy":"validation","validationCode":"from s16_workflow_runtime import _read_snapshot, WORKFLOWS\nsnap = _read_snapshot(run_id)\nassert snap[\"workflowName\"] == name, (\n    f\"runId belongs to {snap['workflowName']}, called with {name}\")","typeGuard":"def run_id_matches(run_id: str, name: str) -> bool:\n    # runIds are wf_<name>_<hex>; cheap prefix check before hitting disk\n    return run_id.startswith(f\"wf_{name}_\")","tryCatchPattern":"try:\n    await run_workflow(name, resume_from_run_id=rid)\nexcept WorkflowInputError as e:\n    if \"does not match workflow meta\" in str(e):\n        actual = _read_snapshot(rid)[\"workflowName\"]\n        return await run_workflow(actual, resume_from_run_id=rid)\n    raise","preventionTips":["Store (workflowName, runId) pairs, not bare runIds, when persisting run history.","Read the workflow name out of the runId prefix (wf_<name>_...) as a fast sanity check.","After renaming a workflow, assume all prior runIds are non-resumable under the new name."],"tags":["workflow","resume","run-id","snapshot","validation"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}