{"record":{"id":"8a771780f2950d72","repo":"github/spec-kit","slug":"error-branch-template-must-include-the-number-t","errorCode":null,"errorMessage":"Error: branch_template must include the {number} token so generated branches remain valid feature branches.","messagePattern":"Error: branch_template must include the (.+?) token so generated branches remain valid feature branches\\.","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"extensions/git/scripts/python/create_new_feature_branch.py","lineNumber":374,"sourceCode":"        return template\n\n    prefix = read_git_config_value(config_file, \"branch_prefix\")\n    if not prefix:\n        return \"\"\n    if prefix.endswith(\"/\"):\n        return f\"{prefix}{{number}}-{{slug}}\"\n    return f\"{prefix}/{{number}}-{{slug}}\"\n\n\ndef validate_branch_template(template: str) -> None:\n    if not template:\n        return\n    if \"{number}\" not in template:\n        _err(\n            \"Error: branch_template must include the {number} token so generated \"\n            \"branches remain valid feature branches.\"\n        )\n        raise SystemExit(1)\n    slug_index = template.find(\"{slug}\")\n    if slug_index != -1 and \"{number}\" in template[slug_index:]:\n        _err(\n            \"Error: branch_template must not place {slug} before {number}; \"\n            \"use {slug} only in the final feature segment.\"\n        )\n        raise SystemExit(1)\n    feature_segment = template.rsplit(\"/\", 1)[-1]\n    if not feature_segment.startswith(\"{number}-\"):\n        _err(\n            \"Error: branch_template must put {number}- at the start of the final \"\n            \"path segment so generated branches remain valid feature branches.\"\n        )\n        raise SystemExit(1)\n\n\ndef render_branch_template(\n    template: str, feature_num: str, branch_suffix: str, author_token: str, app_token: str","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/extensions/git/scripts/python/create_new_feature_branch.py#L356-L392","documentation":"_ensure_safe_shared_directory() was called with create=False, meaning it must only use directories that already exist, and a component of the shared-infra directory is missing. This is the non-creating validation mode used, for example, by _ensure_safe_shared_destination(parent_must_exist=True) before writing a file: the parent chain must already be in place.","triggerScenarios":"Writing a shared-infra file whose parent directory has not been created yet (e.g. .specify/shared/scripts missing at write time); deleting part of the .specify tree between install steps; running a step that assumes a previous step created the directory when it did not (interrupted init, failed prior command).","commonSituations":"Interrupted or partially failed `specify init`/install leaving .specify incomplete; manual cleanup with rm -rf .specify/* between operations; concurrent runs where one deleted directories the other expects; upgrading versions whose directory layout changed.","solutions":["Recreate the directory tree first: let the install/setup flow (which uses create=True) run to completion before file writes","If a previous step failed, rerun it or rerun `specify init` so the full directory skeleton is created","Avoid deleting .specify subdirectories mid-flow; clean the whole tree and start over instead","If orchestrating manually, mkdir -p the parent chain before invoking the write step"],"exampleFix":"# before: only the file-write step ran\n_write_shared_text(proj, proj/'.specify'/'shared'/'scripts'/'s.sh', s)  # parent missing\n\n# after: ensure skeleton exists first\n_ensure_safe_shared_directory(proj, proj/'.specify'/'shared'/'scripts', create=True)\n_write_shared_text(proj, proj/'.specify'/'shared'/'scripts'/'s.sh', s)","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef parent_chain_exists(project: Path, dest: Path) -> bool:\n    return dest.parent.exists() and dest.parent.is_dir()\n\nif not parent_chain_exists(project_path, dest):\n    dest.parent.mkdir(parents=True, exist_ok=True)  # or run the full install step first","typeGuard":null,"tryCatchPattern":"try:\n    _ensure_safe_shared_destination(project_path, dest, parent_must_exist=True)\nexcept ValueError as e:\n    if 'does not exist' in str(e):\n        dest.parent.mkdir(parents=True, exist_ok=True)\n        _ensure_safe_shared_destination(project_path, dest, parent_must_exist=True)\n    else:\n        raise","preventionTips":["Run install/scaffold steps to completion before write steps that assume parents exist","Don't rm -rf parts of .specify between pipeline stages; reset the whole tree instead","In custom pipelines, mkdir -p the target parent chain before invoking writes"],"tags":["filesystem","directory","workflow"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}