Skip to content

Windows/Git Bash: python3 App Execution Alias stub defeats feature.json parser fallback in common.sh (sh variant) #3304

Description

@dulguun0225

Summary

On a stock Windows machine (Git for Windows only — no jq, no real Python on PATH), every bash-variant script that reads .specify/feature.json fails with ERROR: Feature directory not found ... immediately after a successful specify init --script sh. The cause is that the JSON parser fallback chain in common.sh selects python3 based on existence (command -v), but on Windows python3 resolves to the Microsoft Store App Execution Alias stub, which exists on PATH yet fails at runtime. The chain then swallows the runtime failure and returns an empty value, and the grep/sed last-resort parser is unreachable because the chain is if/elif/else on availability, not on parse success.

Environment

  • Spec Kit v0.12.3 (installed via uv tool/uvx from the git tag)
  • Windows 11, Git for Windows (bash 5.2.37, MSYS), run under Git Bash
  • No jq installed (Git for Windows does not ship one)
  • No real Python on PATH; C:\Users\<user>\AppData\Local\Microsoft\WindowsApps\python3.exe stub present (Windows default)

Reproduction

# on the machine described above, in Git Bash
uvx --from "git+https://github.com/github/spec-kit.git@v0.12.3" \
  specify init target --integration generic \
  --integration-options "--commands-dir .agent/commands" \
  --script sh --ignore-agent-tools
cd target && git init -b main . && git add -A && git commit -m scaffold
bash .specify/scripts/bash/create-new-feature.sh --json --short-name demo "demo feature"
# ^ succeeds, persists .specify/feature.json = {"feature_directory":"specs/001-demo"}
bash .specify/scripts/bash/setup-plan.sh --json
# ERROR: Feature directory not found. Set SPECIFY_FEATURE_DIRECTORY or ensure
#        .specify/feature.json contains feature_directory.

feature.json exists and contains the key — it just can't be read:

$ command -v python3
/c/Users/<user>/AppData/Local/Microsoft/WindowsApps/python3
$ python3 -c "print(42)"; echo exit=$?
Python was not found; run without arguments to install from the Microsoft Store, ...
exit=49

Root cause

scripts/bash/common.sh, read_feature_json_feature_directory() (v0.12.3, ~lines 95–120):

if command -v jq >/dev/null 2>&1; then
    ... jq ...
elif command -v python3 >/dev/null 2>&1; then   # <- stub passes this test
    if ! _fd=$(python3 -c "..." 2>/dev/null); then  # <- fails at runtime (exit 49)
        _fd=''                                       # <- failure swallowed
    fi
else
    ... grep/sed fallback ...                        # <- unreachable
fi

create-new-feature.sh masks the problem on its own persist path (it falls back to printf for writing), so the failure only appears one script later, which makes it look like state corruption rather than a parser issue.

Notably, CI runners (GitHub Actions windows-latest etc.) never see this: they ship both jq and a real python3. It only bites real end-user Windows machines — which are exactly the machines the sh-variant + Git Bash path is meant to serve.

Suggested fix

Any of these would do (first is smallest):

  1. Runtime-probe instead of existence-probe: python3 -c 'print(0)' >/dev/null 2>&1 before committing to the python3 branch (the stub also fails this, exit 49).
  2. Fall through the chain on parse failure rather than returning empty (jqpython3grep/sed as successive attempts, not exclusive branches).
  3. Prefer python over python3 on MSYS/Windows, or check both.

The same existence-vs-runtime pattern may exist in other scripts that shell out to python3; worth a quick grep.

Workaround (for anyone else hitting this)

Install jq, disable the python3 App Execution Alias, or expose a real interpreter as python3 (e.g. one managed by uv python install).

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions