Skip to content

hooks: last-resort python3 probe launches the Microsoft Store redirector on Windows (visible console flash, exit 9009) #4563

Open

Description

@leonjeng

Where: graphify/hooks.py, _PYTHON_DETECT, the "Last resort" block — python3 -c "$_GFY_PROBE" is tried before python -c … (0.9.92: L131–135; same order back to 0.8.36 L64–68).

What happens on Windows: with the Microsoft Store app-execution alias enabled (the Windows 10/11 default) and no Store Python installed, command -v python3 in Git Bash resolves to /c/Users/<me>/AppData/Local/Microsoft/WindowsApps/python3 — the AppInstallerPythonRedirector.exe stub. Running it opens a visible console window for ~1.1 s, then exits 9009. So on any machine where the pinned interpreter, .graphify_python, the launcher shebang and the uv-tools scan all miss (removed venv, graphify moved to another env, GUI git client with a minimal PATH), every commit flashes a terminal window before the hook falls through to python.

Environment: Windows 11 Home 23H2 (build 22631), Git for Windows, Windows Terminal 1.24 as default terminal, CPython 3.11.9 (per-user install under %LOCALAPPDATA%\Programs\Python, not the Store build), graphifyy 0.8.36 (probe block unchanged in 0.9.92).

Repro (Git Bash, alias on, no Store Python):

command -v python3          # -> /c/Users/<me>/AppData/Local/Microsoft/WindowsApps/python3
time python3 --version      # console window appears for ~1.1 s; exit code 9009

Measured three times from a hidden launcher: ~1.1 s each, one AppInstallerPythonRedirector.exe + OpenConsole.exe per call.

Caveat: on my machine the hook never reached this branch (the pinned interpreter has graphify), so this is measured on the alias directly, not through a hook run.

Suggested fix (either):

  • on Windows (uname -s = MINGW*/MSYS*/CYGWIN*) probe python before python3; or
  • skip a python3 whose resolved path contains /WindowsApps/ (case "$(command -v python3)" in */WindowsApps/*) ;; esac).

Related: #287 noted the WindowsApps stub's exit code for the AGENTS.md command; #1416 touches the python3 fallback in skill-claw.md. Neither covers the hook probe or the window flash. The console-window burst from DETACHED_PROCESS is #2253 (fixed in 0.9.29) and is a different mechanism.

Activity

  1. github-actions commented on Oct 19, 2026

    @github-actions

    Thanks for opening this issue, @leonjeng. A maintainer will take a look soon.

    If you would like to discuss it in real time, come say hi on our Discord server. For longer-form questions and ideas there is also GitHub Discussions.

    To help us triage, please make sure the report includes what you expected, what actually happened, and the steps (and a small sample) to reproduce it.

  2. Deepjyoti-Sarmah commented on Oct 19, 2026

    @Deepjyoti-Sarmah
    Contributor

    Thanks for the precise report. I checked it against v8 (86c57be). The last-resort block in _PYTHON_DETECT (hooks.py:131) tries python3 before python on every platform, so on a machine with the Store alias and python.org's CPython, the hook runs the stub first every time probes 1 to 4 miss.

    I don't have a Windows machine, so I reproduced the probe order on Linux instead. I put a fake WindowsApps/python3 at the front of PATH that logs its call, sleeps 1 s and exits 9009, with a real python behind it. Then I ran the v8 probe block. The stub was called first and python was chosen after it, 1.07 s in total.

    I have a fix on a branch. It follows your first suggestion: when WINDIR or MSYSTEM is set, the last resort tries python before python3. That's the same Windows check hooks.py already uses for its pipe-handle handling. Everywhere else the order stays python3, then python. Probes 1 to 4, the probe itself, and the "could not locate a Python" message are unchanged. I didn't take the /WindowsApps/ skip, because a real Store Python also lives in WindowsApps, and skipping it there would leave those users with no fallback.

    Tests, with sh-script fakes and only the fake interpreters on PATH:

    • MSYSTEM=MINGW64 or WINDIR set: the stub is neen. Both fail on v8.
    • Neither set: python3 is still tried first.
    • On Windows, if python lacks graphify, the hoo
    • If nothing works, the warning and exit 0 are unchanged.

    I also ran the block under dash and BusyBox ash, and both behave the same.

    Limits:

    1. None of this ran on Windows. If you can try the branch on your machine once the PR is up, that would close the 2. Installed hooks keep the old order until grain.
    2. If python is itself a Store stub (no real Python on PATH), it still runs once before the warning.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions