You install a tool. You open a fresh terminal, run where ffmpeg, and it prints a path right away. Then you go back to your IDE, or your desktop app, or your agent, and it tells you the tool isn't installed. Same machine, same PATH, two different answers.
I've hit this twice in the last month: once with git inside a code agent's worktree manager, and once with ffmpeg inside an MCP subprocess. Both people had already checked PATH, so they figured the app was broken. Most of the time it isn't. Windows handed that app a copy of the environment from an earlier point in time, and nothing ever told it things changed.
Every process gets a frozen copy of the environment
Windows builds an environment block when it creates a process. Microsoft's docs are blunt about it: "By default, a child process inherits the environment variables of its parent process." So your app, the helper processes it spawns, the extension host it loads and every tool it shells out to all keep the block they were born with. Editing PATH afterwards doesn't reach back into a running process.
When you add a directory to PATH, Windows writes it to the registry (machine-wide under HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment, per-user under HKCU\Environment) and broadcasts a WM_SETTINGCHANGE message with lParam set to the string Environment. The docs say that broadcast is what lets "applications, such as the shell, to pick up your updates." The word to notice there is shell. Explorer refreshes its environment, and anything Explorer launches after that inherits the fresh copy. Anything already running keeps the old one, and so does everything it spawns from then on.
That's the whole mechanism. There's no cache to clear and no config to reload.
Diagnosing it in about a minute
- Open a new terminal window and run
where ffmpeg(orwhere git). If that fails too, the app isn't your problem. Your PATH edit didn't stick. - Check when the app actually started:
Get-Process -Name Code,cherry-studio -ErrorAction SilentlyContinue | Select-Object Id, ProcessName, StartTime
If that start time is older than your PATH edit, you can stop here.
- Ask the app what it saw. Plenty of tools log the lookup they performed: an IDE extension's output channel, or an MCP server's stderr line like
FFmpeg not found at: ffmpeg. - Look at both halves of PATH, because Windows combines them when it builds the effective value for a new process:
[Environment]::GetEnvironmentVariable('Path','Machine')
[Environment]::GetEnvironmentVariable('Path','User')
Machine entries come first in the combined list, so if two directories contain a copy of the tool, the earlier one wins. It isn't always the copy you meant.
Restart the process, not the window
- Quit the app completely, then check Task Manager for leftovers: extension hosts, tray helpers, node or electron children, sidecars. A lot of desktop apps are single-instance, so reopening while the old process is still alive just shows you the same stale window with the same stale environment. Kill the leftovers first.
- If you launched the app from a terminal, close that terminal as well. It took its environment when it opened, and the app inherited it from there. A shell started from another shell has the same problem one level up.
- Log off and back on if the change was machine-wide and the app is stubborn. You get a fresh Explorer and a fresh session environment instead of fighting the old one.
- Services and scheduled tasks get none of this. Their host processes started at boot, so they keep the PATH from boot until you restart the service or reboot. Logging off doesn't touch them.
When the restart doesn't help
The git thread above is the awkward version: git worked in VS Code's integrated terminal, worked in Visual Studio, worked when typed by hand, and the extension still said "Git is not installed or found in PATH." Restarts and a reboot changed nothing.
When the environment is definitely fresh and the tool still isn't found, the app isn't using PATH the way you think it is. The usual reasons:
- It runs its own detection with a hardcoded list of locations instead of consulting PATH, and your install isn't on that list.
- It resolves the wrong name. Git for Windows ships
git.exeunder bothcmd\andbin\, and a tool pointed at one of them while looking for the other will fail even thoughgitworks fine for you. On Windows a spawn without a shell doesn't apply PATHEXT either, so a baregitcan fail wheregit.exesucceeds. - There's more than one copy. Run
where gitand count the lines. A PortableGit bundled inside another client, a WSL git and your own install are all candidates, and the first one in the combined PATH wins.
The durable fix is to stop relying on inheritance. Point the app at the absolute path in its own settings (a git.path style key, or whatever the equivalent is), or give it an explicit environment block. For an MCP server that's normally an env entry in the config:
"env": { "PATH": "C:\\ffmpeg\\bin;<your existing PATH here>" }
Some clients expand ${PATH} for you and some don't, so check yours before assuming either way.
One thing to watch if you edit PATH with setx: it crops values at 1024 characters, silently, so a long PATH loses entries off the end. The documented maximum size of a single environment variable is 32,767 characters, and if you're anywhere near that, something else in your setup needs a look.
Where this usually lands
Restarting an app solves this more often than it sounds like it should, but restart means the process, not the window. If a full restart and a reboot both fail, stop suspecting the environment. The tool is probably fine, and the app's own lookup logic is what to read next.
Both cases came from real threads: the git one is Kilo-Org/kilocode#13452 and the ffmpeg one is CherryHQ/cherry-studio#18528. I've only had eyes on those two, so your mileage may vary. Hope this helps.
Top comments (0)