{"record":{"id":"04f7099d363f0f5b","repo":"github/spec-kit","slug":"error-short-name-requires-a-value","errorCode":null,"errorMessage":"Error: --short-name requires a value","messagePattern":"Error: --short-name requires a value","errorType":"console","errorClass":"SystemExit","httpStatus":null,"severity":"error","filePath":"extensions/git/scripts/python/create_new_feature_branch.py","lineNumber":104,"sourceCode":"    use_timestamp: bool = False\n    description_parts: list[str] = field(default_factory=list)\n\n\ndef parse_args(argv: list[str]) -> Args:\n    args = Args()\n    i = 0\n    while i < len(argv):\n        arg = argv[i]\n        if arg == \"--json\":\n            args.json_mode = True\n        elif arg == \"--dry-run\":\n            args.dry_run = True\n        elif arg == \"--allow-existing-branch\":\n            args.allow_existing = True\n        elif arg == \"--short-name\":\n            if i + 1 >= len(argv) or argv[i + 1].startswith(\"--\"):\n                _err(\"Error: --short-name requires a value\")\n                raise SystemExit(1)\n            i += 1\n            args.short_name = argv[i]\n        elif arg == \"--number\":\n            if i + 1 >= len(argv) or argv[i + 1].startswith(\"--\"):\n                _err(\"Error: --number requires a value\")\n                raise SystemExit(1)\n            i += 1\n            args.branch_number = argv[i]\n            if not re.fullmatch(r\"[0-9]+\", args.branch_number):\n                _err(\"Error: --number must be a non-negative integer\")\n                raise SystemExit(1)\n        elif arg == \"--timestamp\":\n            args.use_timestamp = True\n        elif arg in (\"--help\", \"-h\"):\n            print(HELP_TEXT)\n            raise SystemExit(0)\n        else:\n            args.description_parts.append(arg)","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/extensions/git/scripts/python/create_new_feature_branch.py#L86-L122","documentation":"_ensure_safe_shared_directory() walks each component of the shared-infrastructure directory relative to the project root and refuses to traverse a component that is a symlink. This is a defense against symlink attacks: even a symlink that points back inside the project could be swapped, so the walk fails closed with SymlinkedSharedPathError (a ValueError subclass) before any directory is created or written into.","triggerScenarios":"Any shared-infra write where an intermediate directory under project_path (e.g. .specify, .specify/shared, .specify/shared/scripts) is a symlink — commonly a developer symlinking .specify/shared to a dotfiles repo or another checkout to 'share' infra between projects.","commonSituations":"Symlinking .specify to a central folder to reuse specs across clones; monorepo setups where shared tooling is a symlink to packages/shared; restoring a project from a backup tool that recreates directories as links; CI caches that materialize paths as symlinks.","solutions":["Replace the symlinked directory with a real directory and copy the contents in (or use cp -aL to dereference)","If sharing between projects is the goal, use a supported mechanism (e.g. presets or a package) instead of symlinking inside the tree","Remove the stale symlink: rm .specify/shared (it is a link, not the data) and let the CLI recreate the directory","Check for symlinks before invoking: p.is_symlink() for each parent component of the destination"],"exampleFix":"# before: .specify/shared -> /home/me/dotfiles/shared\n$ specify init  # raises SymlinkedSharedPathError\n\n# after\n$ rm .specify/shared && cp -a /home/me/dotfiles/shared .specify/shared\n$ specify init  # ok","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef parents_are_real_dirs(project: Path, rel_dir: Path) -> bool:\n    cur = project\n    for part in rel_dir.parts:\n        cur = cur / part\n        if cur.is_symlink():\n            return False\n    return True\n\nassert parents_are_real_dirs(project_path, rel_dir)","typeGuard":null,"tryCatchPattern":"from specify_cli.shared_infra import SymlinkedSharedPathError\n\ntry:\n    _ensure_safe_shared_directory(project_path, directory)\nexcept SymlinkedSharedPathError as e:\n    print(f'found symlinked component: {e}; replace links with real dirs')\n    raise","preventionTips":["Keep .specify and its subdirectories as real directories; never symlink them","Add a repo policy check (or CI lint) that fails when find .specify -type l returns results","Prefer supported sharing (presets/packages) over symlink tricks"],"tags":["filesystem","symlink","security"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}