{"record":{"id":"b1934fe2510b75d5","repo":"shareAI-lab/learn-claude-code","slug":"meta-name-must-be-a-1-64-character-slug-using-lett","errorCode":null,"errorMessage":"meta.name must be a 1-64 character slug using letters, numbers, '.', '_', or '-'","messagePattern":"meta\\.name must be a 1-64 character slug using letters, numbers, '\\.', '_', or '-'","errorType":"validation","errorClass":"WorkflowInputError","httpStatus":null,"severity":"error","filePath":"s16_workflow_runtime/code.py","lineNumber":127,"sourceCode":"            try:\n                fcntl.flock(handle.fileno(), fcntl.LOCK_UN)\n            finally:\n                handle.close()\n        local_lock.release()\n        with _run_locks_guard:\n            if not local_lock.locked() and _run_locks.get(run_id) is local_lock:\n                _run_locks.pop(run_id, None)\n\n\n# -- Metadata Validation --\ndef validate_meta(meta):\n    \"\"\"Validate name, description, and optional phases before launch.\"\"\"\n    if not isinstance(meta, dict):\n        raise WorkflowInputError(\"meta must be an object literal\")\n    if not meta.get(\"name\") or not meta.get(\"description\"):\n        raise WorkflowInputError(\"meta requires `name` and `description`\")\n    if not isinstance(meta[\"name\"], str) or not WORKFLOW_NAME_RE.fullmatch(meta[\"name\"]):\n        raise WorkflowInputError(\n            \"meta.name must be a 1-64 character slug using letters, numbers, '.', '_', or '-'\"\n        )\n    if not isinstance(meta[\"description\"], str):\n        raise WorkflowInputError(\"meta.description must be a string\")\n    if \"phases\" in meta:\n        if not isinstance(meta[\"phases\"], list) or not all(\n            isinstance(phase, str) and phase for phase in meta[\"phases\"]\n        ):\n            raise WorkflowInputError(\"meta.phases must be a list of non-empty strings\")\n    return meta\n\n\ndef check_permission(meta, settings=None):\n    \"\"\"Apply the s03 allow/deny gate before launching a workflow.\"\"\"\n    settings = settings or {}\n    if meta[\"name\"] in settings.get(\"deny\", []):\n        raise WorkflowInputError(f\"workflow '{meta['name']}' denied by settings\")\n    return \"allow\"","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s16_workflow_runtime/code.py#L109-L145","documentation":"meta.name must fully match ^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$ : 1-64 characters, starting with a letter or digit, containing only letters, digits, '.', '_', '-'. The strictness exists because the name is embedded in the run id, filesystem paths (<runId>.json, .journal.jsonl, .lock), and the permission allow/deny lists — spaces or slashes would break all three.","triggerScenarios":"Names with spaces ('data pipeline'), leading separators ('-ingest'), colons or other punctuation ('ingest:v2'), unicode characters, or names longer than 64 characters. Names starting with '.' or '-' fail the first-character rule.","commonSituations":"Using human-readable titles as the machine name. Copying Docker image tags or version strings ('ingest:latest') into name. Auto-generating names from free text without slugification.","solutions":["Slugify: lowercase, replace whitespace/punctuation with '-', strip leading separators","Move version info into description or keep it after a '.'/'-' that is not the first character","Apply the same regex client-side before submitting to run()"],"exampleFix":"# before\nmeta = {\"name\": \"Data Pipeline (nightly)\", \"description\": \"...\"}\n\n# after\nmeta = {\"name\": \"data-pipeline-nightly\", \"description\": \"...\"}","handlingStrategy":"validation","validationCode":"import re\nNAME_RE = re.compile(r\"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$\")\n\ndef is_valid_workflow_name(name) -> bool:\n    return isinstance(name, str) and bool(NAME_RE.fullmatch(name))\n\nassert is_valid_workflow_name(meta[\"name\"]), f\"invalid workflow name: {meta['name']!r}\"","typeGuard":"def is_slug_name(name) -> bool:\n    import re\n    return isinstance(name, str) and bool(re.fullmatch(r\"[A-Za-z0-9][A-Za-z0-9._-]{0,63}\", name))","tryCatchPattern":"try:\n    validate_meta(meta)\nexcept WorkflowInputError as exc:\n    if \"meta.name\" in str(exc):\n        import re as _re\n        slug = _re.sub(r\"[^A-Za-z0-9._-]+\", \"-\", meta[\"name\"]).strip(\"-.\")[:64]\n        meta = {**meta, \"name\": slug}\n        validate_meta(meta)\n    else:\n        raise","preventionTips":["Slugify free-text names before launch","Keep names <= 46 chars if you also want valid run ids","Apply the regex client-side in forms/UIs that collect names"],"tags":["workflow","validation","naming","metadata"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}