{"record":{"id":"24ff470b504017d3","repo":"github/spec-kit","slug":"error-feature-description-cannot-be-empty-or-cont","errorCode":null,"errorMessage":"Error: Feature description cannot be empty or contain only whitespace","messagePattern":"Error: Feature description cannot be empty or contain only whitespace","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/python/create_new_feature.py","lineNumber":155,"sourceCode":"        elif arg == \"--timestamp\":\n            use_timestamp = True\n        elif arg in {\"--help\", \"-h\"}:\n            sys.stdout.write(_help_text(argv0))\n            raise SystemExit(0)\n        else:\n            rest.append(arg)\n        i += 1\n\n    description = \" \".join(rest).strip()\n    if not description:\n        if rest:\n            print(\n                \"Error: Feature description cannot be empty or contain only whitespace\",\n                file=sys.stderr,\n            )\n        else:\n            print(_usage(argv0), file=sys.stderr)\n        raise SystemExit(1)\n\n    return Args(\n        json_mode=json_mode,\n        dry_run=dry_run,\n        allow_existing=allow_existing,\n        short_name=short_name,\n        branch_number=branch_number,\n        use_timestamp=use_timestamp,\n        description=description,\n    )\n\n\ndef _clean_branch_name(name: str) -> str:\n    cleaned = re.sub(r\"[^a-z0-9]\", \"-\", name.lower())\n    cleaned = re.sub(r\"-+\", \"-\", cleaned)\n    return cleaned.strip(\"-\")\n\n","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/github/spec-kit/blob/bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c/scripts/python/create_new_feature.py#L137-L173","documentation":"After flag parsing, all remaining positional arguments are joined into the feature description. If the user passed positional text (rest is non-empty) but it strips to empty — only whitespace — the script rejects it with this error instead of silently creating a whitespace-named branch; if nothing positional was passed at all it prints generic usage instead.","triggerScenarios":"Calling create_new_feature.py \"   \" or with quoted spaces \"Add  \" as the only positional argument; passing flags only but with a stray quoted empty string \"\" among positionals (rest non-empty, description empty).","commonSituations":"A wrapper script passing an unset-but-quoted variable (\"$DESC\" with DESC empty makes rest=[\"\"]); copy-paste commands where the description was deleted but the quotes left; descriptions made only of tabs/newlines.","solutions":["Pass a real description: python create_new_feature.py \"Add user login\".","In wrapper scripts, default or validate the variable first: DESC=\"${DESC:-untitled-feature}\".","Drop stray empty-string arguments (\"\" or ' ') from the command line."],"exampleFix":"# before\npython create_new_feature.py \"$DESC\"   # DESC unset/whitespace\n# after\nDESC=\"${DESC:-untitled-feature}\"\npython create_new_feature.py \"$DESC\"","handlingStrategy":"validation","validationCode":"import sys\n\npositional = [a for a in sys.argv[1:] if not a.startswith(\"--\")]\ndescription = \" \".join(positional).strip()\nif not description:\n    sys.exit(\"Feature description is required\")","typeGuard":null,"tryCatchPattern":"try:\n    args = parse_args(argv)\nexcept SystemExit:\n    raise  # fix the invocation; do not retry","preventionTips":["Default or validate the description variable in wrapper scripts before invoking.","Remove stray quoted empty strings from the command line.","Description must contain at least one non-whitespace character."],"tags":["cli","validation","shell"],"backgroundTag":null,"analyzedSha":"bf88c9f9a82fa370c7a7257aa2b3cf10b457b65c","analyzedAt":"2026-08-14T19:43:37.150Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}