{"record":{"id":"9074e6111bac33e6","repo":"shareAI-lab/learn-claude-code","slug":"invalid-workflow-runid","errorCode":null,"errorMessage":"invalid workflow runId","messagePattern":"invalid workflow runId","errorType":"exception","errorClass":"WorkflowInputError","httpStatus":null,"severity":"error","filePath":"s16_workflow_runtime/code.py","lineNumber":75,"sourceCode":"    for _ in range(32):\n        run_id = validate_run_id(create_run_id(meta))\n        snapshot_path = STORE / f\"{run_id}.json\"\n        try:\n            fd = os.open(snapshot_path, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o600)\n        except FileExistsError:\n            continue\n        os.close(fd)\n        return run_id\n    raise WorkflowInputError(\"could not allocate a unique workflow runId\")\n\n\ndef create_task_id(run_id) -> str:\n    return f\"local_workflow_{run_id}\"\n\n\ndef validate_run_id(run_id):\n    if not isinstance(run_id, str) or not RUN_ID_RE.fullmatch(run_id):\n        raise WorkflowInputError(\"invalid workflow runId\")\n    return run_id\n\n\n# -- Errors --\nclass WorkflowInputError(Exception):\n    \"\"\"Bad workflow, metadata, or schema input.\"\"\"\n\n\n_run_locks_guard = threading.Lock()\n_run_locks: dict[str, threading.Lock] = {}\n\n\n@contextmanager\ndef workflow_run_lock(run_id: str):\n    \"\"\"Hold one run across threads and host processes for its full lifecycle.\"\"\"\n    with _run_locks_guard:\n        local_lock = _run_locks.setdefault(run_id, threading.Lock())\n    if not local_lock.acquire(blocking=False):","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s16_workflow_runtime/code.py#L57-L93","documentation":"validate_run_id enforces the canonical shape ^wf_[A-Za-z0-9][A-Za-z0-9._-]{0,63}_[0-9a-f]{16}$ — the 'wf_' prefix, a slug body of at most 64 characters, and a 16-lowercase-hex suffix. Any run_id that is not a string, or deviates from that shape, raises WorkflowInputError. Internally it also acts as a backstop on create_run_id output: because the slug portion shares the 64-character budget with the fixed affixes, a workflow name longer than 46 characters makes even a freshly generated id invalid.","triggerScenarios":"Passing a user-supplied or hand-built run_id like 'my-run' or 'WF_docs_abc123' to resume(). Copying a run id with the hex suffix uppercased or truncated. Naming a workflow with 47+ characters, since wf_ + name + _ + 16 hex exceeds the pattern.","commonSituations":"Scripts that store run ids in configs and resume them later, with edits/corruption in transit. Teams assuming the 64-char WORKFLOW_NAME_RE budget applies fully to run ids. Manually constructing ids instead of using reserve_run_id.","solutions":["Only use ids returned by reserve_run_id/run; never hand-build them","Keep workflow meta.name to 46 characters or fewer so generated ids always validate","If resuming, copy the id verbatim (lowercase hex, full 16 chars) from the store listing"],"exampleFix":"# before\nrun_id = f\"wf_{workflow_name}_{uuid4().hex[:12]}\"  # wrong shape, wrong hex length\n\n# after\nrun_id = reserve_run_id(meta)  # wf_<slug>_<16 lowercase hex>, pre-validated","handlingStrategy":"validation","validationCode":"import re\nRUN_ID_RE = re.compile(r\"^wf_[A-Za-z0-9][A-Za-z0-9._-]{0,63}_[0-9a-f]{16}$\")\n\ndef is_valid_run_id(run_id) -> bool:\n    return isinstance(run_id, str) and bool(RUN_ID_RE.fullmatch(run_id))\n\nassert is_valid_run_id(run_id), f\"malformed run id: {run_id!r}\"","typeGuard":"def is_valid_run_id(run_id) -> bool:\n    import re\n    return isinstance(run_id, str) and bool(re.fullmatch(r\"wf_[A-Za-z0-9][A-Za-z0-9._-]{0,63}_[0-9a-f]{16}\", run_id))","tryCatchPattern":"try:\n    validate_run_id(run_id)\nexcept WorkflowInputError:\n    # do not hand-repair ids; list the store and pick a real one, or reserve a new one\n    run_id = reserve_run_id(meta)","preventionTips":["Treat run ids as opaque tokens produced by reserve_run_id","Keep meta.name <= 46 chars so generated ids always fit the pattern","Persist ids unedited (no trimming, no uppercase)"],"tags":["workflow","run-id","validation","naming"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}