Skip to content

Build1 publisher3 min readPublished

A running Windows process keeps the PATH it inherited at creation

A fresh terminal resolves ffmpeg while the IDE on the same machine says the tool is missing. The difference is the environment block each process got when it was created, and Windows sends no update to a process already running.

The Engineer · Build desk

What happened

  • Microsoft's documentation says a child process inherits its parent's environment variables by default, so a running app keeps the environment block it was handed at creation.
  • The dev.to writeup's author says he hit this twice in a month, with git inside a code agent's worktree manager and ffmpeg inside an MCP subprocess, in both cases after PATH had been checked.
  • In the git case, the extension reported "Git is not installed or found in PATH" while git worked in VS Code's integrated terminal, in Visual Studio and typed by hand, and restarts and a reboot changed nothing.
  • Services and scheduled tasks keep the PATH they had at boot until the service is restarted or the machine reboots, and logging off does not reach them.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • exposure Agent and MCP subprocesses report on the environment of whatever spawned them, so a tool-not-found line in an agent log describes the parent's PATH at launch time and not the machine's current PATH.
  • constraint Keeping PATH tidy cannot fix a shell-less spawn, because PATHEXT is not applied there and an app looking for a bare git will miss a git.exe that resolves fine for a human.
  • cost The diagnosis costs one Get-Process call comparing start time against the time of the edit; skipping it sends the engineer back to reinstalling a tool that is already installed.

The registry write and the window message are separate events, and only one of them touches a running process. Adding a directory to PATH writes it under `HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment` for machine scope, or `HKCU\Environment` per user [3]. Windows then broadcasts `WM_SETTINGCHANGE` with `lParam` set to the string `Environment` [4]. Microsoft's documentation, as quoted in the dev.to writeup, says that broadcast is what allows "applications, such as the shell, to pick up your updates" [4]. Explorer does pick it up, and anything Explorer launches afterwards gets the fresh copy [5]. Everything already alive keeps the block it was created with, along with every child it spawns from then on [5]. There is no cache to clear and no config to reload [20].

Two lists feed that block. `[Environment]::GetEnvironmentVariable('Path','Machine')` and the same call with `'User'` show what Windows combines when it builds the effective PATH for a new process, machine entries first [9]. When two directories each hold a copy of the tool, the earlier entry wins, and the writeup notes it is not always the copy you meant [9].

The writeup lists eight checks. Four of them end in terminating something: quit the app and clear leftover extension hosts, tray helpers and node or electron children from Task Manager; close the terminal you launched it from; log off and back on after a machine-wide change; restart the service or reboot for services and scheduled tasks [1]. Single-instance apps make the first of those harder than it sounds, because reopening while the old process is still alive returns the same stale window with the same stale environment [10]. Reinstalling the tool does not change the environment block of a process that started yesterday.

The cheapest check comes first. Open a new terminal and run `where ffmpeg` or `where git`; if that fails too, the PATH edit itself never stuck [7]. Then compare the app's start time with the time of the edit using `Get-Process -Name Code,cherry-studio | Select-Object Id, ProcessName, StartTime` [8]. Many tools also log the lookup they performed, an IDE extension in its output channel or an MCP server on stderr with a line like `FFmpeg not found at: ffmpeg` [19].

The author says he hit this twice in a month and that most of the time the app is not broken [6]. That frequency is one developer's sample. The inheritance rule is documented behaviour: "By default, a child process inherits the environment variables of its parent process" [1].

When the environment is genuinely fresh and the lookup still fails, the app is not consulting PATH the way you assume. Git for Windows ships `git.exe` under both `cmd\` and `bin\`, so a tool pointed at one directory while looking for the other fails even though `git` works when typed by hand [16]. A spawn without a shell does not apply PATHEXT on Windows, and a bare `git` can fail where `git.exe` succeeds [17]. Some apps run their own detection against a hardcoded list of locations and never read PATH at all [15]. Where `where git` prints more than one line, count them: a PortableGit bundled inside another client, a WSL git and your own install are all candidates [18].

What to watch

  • Whether MCP hosts and agent runtimes start logging the resolved executable path and the PATH they actually searched.
  • Whether the VS Code git extension case is fixed in its detection logic or stays a process-lifecycle support answer.
  • Whether any supported way appears for a running process to re-read the Environment registry keys without restarting.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories