Skip to content

Edge Case: Mason fails to make Python tools executable when global pip.conf has user = true #1937

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
2 tasks done
moyeh04 opened this issue May 9, 2025 · 0 comments
Open
2 tasks done

Comments

@moyeh04
Copy link

moyeh04 commented May 9, 2025

I've searched open issues for similar requests

  • Yes

I've recently downloaded the latest plugin version of mason.nvim

  • Yes

Problem description

When installing any Python-based tool with Mason (e.g., yamlfix, htmlbeautifier, ruff, anything that uses pip via Mason), the installation appears to complete (pip exit code 0 in Mason DEBUG logs), but Mason then reports:

Failed to find executable "TOOL_NAME"(like ruff) in Python virtual environment.
and subsequently deletes the package installation directory.

This happens because a global pip.conf setting [global] user = true makes pip install packages into the user's global site-packages instead of the virtual environment Mason creates for the tool.
Mason then correctly cannot find the executable in the expected venv path.

  • Mason's process for installing Python tools relies on pip correctly populating the virtual environment it creates.

  • The global pip.conf [user = true] is a common user configuration that directly conflicts with and breaks Mason's expectation of where pip should install packages for a given tool.

  • Mason's current behavior (including creating venvs with --system-site-packages as seen in DEBUG logs, which might add to confusion when user=true is also set) doesn't seem to detect or mitigate this common pip configuration, leading to failed installations that are hard for users to diagnose.

Solution:

Mason should definitely warn about a global pip.conf [user = true] conflict, maybe with a message like "Your global pip.conf has 'user = true', which will break Python tool installations in Mason. Please remove or set it to false."

Beyond just a warning, to actively fix this when Mason calls pip, Mason should try to force pip to behave. It could do this by setting an environment variable PIP_USER=false specifically for the pip commands it runs. This should override my bad pip.conf setting and make pip install packages into the virtual environment where they actually belong.

I had user = true in my global pip.conf for reasons I don't even remember, which is why this felt like an edge case until we figured it out.

Expected behavior

I've reproduced the error itself:

First have this in pip.conf

File: pip.conf
────────────────
 [global]
 user = true

Second This shell script that mimics the behavior when Mason installs packages using pip

TEST_PACKAGE_NAME="yamlfix"
TEST_PACKAGE_VERSION="1.17.0"
TEST_BASE_DIR="$HOME/tmp_mason_yamlfix_isolated_test"
PACKAGE_DIR="$TEST_BASE_DIR/packages/$TEST_PACKAGE_NAME"
VENV_DIR="$PACKAGE_DIR/venv"
rm -rf "$PACKAGE_DIR"
echo "INFO: Creating directory: $PACKAGE_DIR"
mkdir -p "$PACKAGE_DIR"
cd "$PACKAGE_DIR"
echo "INFO: Current directory is now: $(pwd)"
echo "INFO: Creating virtual environment in $VENV_DIR (NO --system-site-packages)..."
python3 -m venv "$VENV_DIR"
echo "INFO: Running pip install command for $TEST_PACKAGE_NAME==$TEST_PACKAGE_VERSION..."
"$VENV_DIR/bin/python" -m pip --disable-pip-version-check --verbose install --ignore-installed "$TEST_PACKAGE_NAME==$TEST_PACKAGE_VERSION"
echo "INFO: Checking installed $TEST_PACKAGE_NAME version with pip show:"
"$VENV_DIR/bin/python" -m pip show "$TEST_PACKAGE_NAME"
echo "INFO: Checking location with pip show again:"
"$VENV_DIR/bin/python" -m pip show "$TEST_PACKAGE_NAME" | grep Location
echo "INFO: Attempting to get $TEST_PACKAGE_NAME version from executable:"
"$VENV_DIR/bin/$TEST_PACKAGE_NAME" --version
echo "INFO: Test complete. You can manually remove the test directory with: rm -rf $TEST_BASE_DIR"

Output

INFO: Creating directory: /home/username/tmp_mason_yamlfix_isolated_test/packages/yamlfix
INFO: Current directory is now: /home/username/tmp_mason_yamlfix_isolated_test/packages/yamlfix
INFO: Creating virtual environment in /home/username/tmp_mason_yamlfix_isolated_test/packages/yamlfix/venv (NO --system-site-packages)...
INFO: Running pip install command for yamlfix==1.17.0...
Using pip 25.0.1 from /home/username/tmp_mason_yamlfix_isolated_test/packages/yamlfix/venv/lib/python3.13/site-packages/pip (python 3.13)
ERROR: Can not perform a '--user' install. User site-packages are not visible in this virtualenv.
INFO: Checking installed yamlfix version with pip show:
WARNING: Package(s) not found: yamlfix
INFO: Checking location with pip show again:
WARNING: Package(s) not found: yamlfix
INFO: Attempting to get yamlfix version from executable:
zsh: no such file or directory: /home/username/tmp_mason_yamlfix_isolated_test/packages/yamlfix/venv/bin/yamlfix
INFO: Test complete. You can manually remove the test directory with: rm -rf /home/username/tmp_mason_yamlfix_isolated_test                                                                                                                                     

Affected packages

All pip packages

Mason output

Failed (1)
   ✗ yamlfix
     ▼ Displaying full log
       Creating virtual environment…
       Installing pip package yamlfix@1.17.0…
       Collecting yamlfix==1.17.0
         Using cached yamlfix-1.17.0-py3-none-any.whl.metadata (2.9 kB)
       Collecting click>=8.1.3 (from yamlfix==1.17.0)
         Using cached click-8.1.8-py3-none-any.whl.metadata (2.3 kB)
       Collecting ruyaml>=0.91.0 (from yamlfix==1.17.0)
         Using cached ruyaml-0.91.0-py3-none-any.whl.metadata (12 kB)
       Collecting maison>=2.0.0 (from yamlfix==1.17.0)
         Using cached maison-2.0.0-py3-none-any.whl.metadata (2.9 kB)
       Collecting pydantic>=2.8.2 (from yamlfix==1.17.0)
         Using cached pydantic-2.11.4-py3-none-any.whl.metadata (66 kB)
       Collecting toml<0.11.0,>=0.10.2 (from maison>=2.0.0->yamlfix==1.17.0)
         Using cached toml-0.10.2-py2.py3-none-any.whl.metadata (7.1 kB)
       Collecting annotated-types>=0.6.0 (from pydantic>=2.8.2->yamlfix==1.17.0)
         Using cached annotated_types-0.7.0-py3-none-any.whl.metadata (15 kB)
       Collecting pydantic-core==2.33.2 (from pydantic>=2.8.2->yamlfix==1.17.0)
         Using cached pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.8 kB)
       Collecting typing-extensions>=4.12.2 (from pydantic>=2.8.2->yamlfix==1.17.0)
         Using cached typing_extensions-4.13.2-py3-none-any.whl.metadata (3.0 kB)
       Collecting typing-inspection>=0.4.0 (from pydantic>=2.8.2->yamlfix==1.17.0)
         Using cached typing_inspection-0.4.0-py3-none-any.whl.metadata (2.6 kB)
       Collecting distro>=1.3.0 (from ruyaml>=0.91.0->yamlfix==1.17.0)
         Using cached distro-1.9.0-py3-none-any.whl.metadata (6.8 kB)
       Collecting setuptools>=39.0 (from ruyaml>=0.91.0->yamlfix==1.17.0)
         Using cached setuptools-80.3.1-py3-none-any.whl.metadata (6.5 kB)
       Using cached yamlfix-1.17.0-py3-none-any.whl (28 kB)
       Using cached click-8.1.8-py3-none-any.whl (98 kB)
       Using cached maison-2.0.0-py3-none-any.whl (10 kB)
       Using cached pydantic-2.11.4-py3-none-any.whl (443 kB)
       Using cached pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.0 MB)
       Using cached ruyaml-0.91.0-py3-none-any.whl (108 kB)
       Using cached annotated_types-0.7.0-py3-none-any.whl (13 kB)
       Using cached distro-1.9.0-py3-none-any.whl (20 kB)
       Using cached setuptools-80.3.1-py3-none-any.whl (1.2 MB)
       Using cached toml-0.10.2-py2.py3-none-any.whl (16 kB)
       Using cached typing_extensions-4.13.2-py3-none-any.whl (45 kB)
       Using cached typing_inspection-0.4.0-py3-none-any.whl (14 kB)
       Installing collected packages: typing-extensions, toml, setuptools, distro, click, annotated-types, typing-inspection, ruyaml, pydantic-core, maison, pydantic, yamlfix
       Successfully installed annotated-types-0.7.0 click-8.1.7 distro-1.9.0 maison-2.0.0 pydantic-2.11.4 pydantic-core-2.33.2 ruyaml-0.91.0 setuptools-80.3.1 toml-0.10.2 typing-extensions-4.13.2 typing-inspection-
       Failed to find executable "yamlfix" in Python virtual environment.

Installation log

[INFO  Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/InstallRunner.lua:40: Executing installer for Package(name=yamlfix) {
  debug = false,
  force = false,
  strict = false
}
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/InstallRunner.lua:188: Acquiring permit for Package(name=yamlfix)
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/InstallRunner.lua:206: Activating handle InstallHandle(package=Package(name=yamlfix), state=QUEUED)
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/InstallRunner.lua:169: Attempting to lock package Package(name=yamlfix)
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/InstallRunner.lua:181: Wrote lockfile Package(name=yamlfix)
[DEBUG Fri May  9 14:49:04 2025] .../.local/share/nvim/lazy/mason.nvim/lua/mason-core/fs.lua:71: fs: mkdirp /home/username/.local/share/nvim/mason/staging/yamlfix
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/compiler/init.lua:147: Compiling installer. yamlfix {
  debug = false,
  force = false,
  strict = false
}
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/managers/pypi.lua:188: pypi: init
[DEBUG Fri May  9 14:49:04 2025] ...azy/mason.nvim/lua/mason-core/installer/context/init.lua:71: Promoting cwd "/home/username/.local/share/nvim/mason/staging/yamlfix" to "/home/username/.local/share/nvim/mason/packages/yamlfix"
[DEBUG Fri May  9 14:49:04 2025] .../.local/share/nvim/lazy/mason.nvim/lua/mason-core/fs.lua:65: fs: mkdir /home/username/.local/share/nvim/mason/packages/yamlfix
[DEBUG Fri May  9 14:49:04 2025] .../.local/share/nvim/lazy/mason.nvim/lua/mason-core/fs.lua:84: fs: rename /home/username/.local/share/nvim/mason/staging/yamlfix /home/username/.local/share/nvim/mason/packages/yamlfix
[DEBUG Fri May  9 14:49:04 2025] ...ocal/share/nvim/lazy/mason.nvim/lua/mason-core/fetch.lua:37: Fetching URL "https://api.mason-registry.dev/api/pypi/yamlfix/versions/1.17.0"
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:189: Spawning cmd="curl", spawn_opts={
  args = { "-H", "Accept: application/vnd.mason-registry.v1+json; q=1.0, application/json; q=0.8", "-H", "User-Agent: mason.nvim v2.0.0 (+https://github.com/mason-org/mason.nvim)", "-fsSL", "-X", "GET", "--connect-timeout", 30, "https://api.mason-registry.dev
api/pypi/yamlfix/versions/1.17.0" }
}
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:235: Spawned with pid 584677
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:221: Job pid=584677 exited with exit_code=0, signal=0
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:189: Spawning cmd="python3", spawn_opts={
  args = { "--version" }
}
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:235: Spawned with pid 584679
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:221: Job pid=584679 exited with exit_code=0, signal=0
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/managers/pypi.lua:90: Resolved stock python3 installation version 3.13.3
[DEBUG Fri May  9 14:49:04 2025] ...zy/mason.nvim/lua/mason-core/installer/managers/pypi.lua:136: Found python3 installation version=3.13.3, executable="python3"
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:189: Spawning cmd="python3", spawn_opts={
  args = { "-m", "venv", "--system-site-packages", "venv" },
  cwd = "/home/username/.local/share/nvim/mason/packages/yamlfix"
}
[DEBUG Fri May  9 14:49:04 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:235: Spawned with pid 584680
[DEBUG Fri May  9 14:49:08 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:221: Job pid=584680 exited with exit_code=0, signal=0
[DEBUG Fri May  9 14:49:08 2025] ...zy/mason.nvim/lua/mason-core/installer/managers/pypi.lua:208: pypi: install "yamlfix" "1.17.0" {
  install_extra_args = {}
}
[DEBUG Fri May  9 14:49:08 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:189: Spawning cmd="/home/username/.local/share/nvim/mason/packages/yamlfix/venv/bin/python", spawn_opts={
  args = { "-m", "pip", "--disable-pip-version-check", "install", "--ignore-installed", "yamlfix==1.17.0" },
  cwd = "/home/username/.local/share/nvim/mason/packages/yamlfix"
}
[DEBUG Fri May  9 14:49:08 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:235: Spawned with pid 584699
[DEBUG Fri May  9 14:49:13 2025] ...al/share/nvim/lazy/mason.nvim/lua/mason-core/process.lua:221: Job pid=584699 exited with exit_code=0, signal=0
[DEBUG Fri May  9 14:49:13 2025] ...zy/mason.nvim/lua/mason-core/installer/compiler/link.lua:139: Registering bin links Package(name=yamlfix) {
  yamlfix = "pypi:yamlfix"
}
[DEBUG Fri May  9 14:49:13 2025] .../.local/share/nvim/lazy/mason.nvim/lua/mason-core/fs.lua:47: fs: rmrf /home/username/.local/share/nvim/mason/packages/yamlfix
[DEBUG Fri May  9 14:49:13 2025] .../.local/share/nvim/lazy/mason.nvim/lua/mason-core/fs.lua:59: fs: unlink /home/username/.local/share/nvim/mason/staging/yamlfix.lock
[ERROR Fri May  9 14:49:13 2025] ...zy/mason.nvim/lua/mason-core/installer/InstallRunner.lua:93: Installation failed for Package(name=yamlfix) error='Failed to find executable "yamlfix" in Python virtual environment.'

Neovim version (>= 0.10.0)

NVIM v0.11.1
Build type: Release
LuaJIT 2.1.1744318430

Operating system/version

Linux 5.15.167.4-microsoft-standard-WSL2 #1 SMP x86_64 x86_64 x86_64 GNU/Linux

Healthcheck

==============================================================================
 mason:                                         require("mason.health").check()

 mason.nvim
 - ✅ OK mason.nvim version v2.0.0
 - ✅ OK PATH: prepend
 - ✅ OK Providers:
     mason.providers.registry-api
     mason.providers.client
 - ✅ OK neovim version >= 0.10.0

 mason.nvim [Registries]
 - ✅ OK Registry github.com/mason-org/mason-registry version: 2025-05-08-sugary-bangle is installed.

 mason.nvim [Core utils]
 - ✅ OK unzip: UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.
 - ✅ OK wget: GNU Wget 1.21.2 built on linux-gnu.
 - ✅ OK curl: curl 8.13.0 (x86_64-pc-linux-gnu) libcurl/8.13.0 OpenSSL/3.5.0 zlib/1.3.1 brotli/1.1.0 zstd/1.5.7 libidn2/2.3.8 libssh2/1.11.1 nghttp2/1.65.0 librtmp/2.3 OpenLDAP/2.6.9
 - ✅ OK gzip: gzip 1.10
 - ✅ OK tar: tar (GNU tar) 1.34
 - ✅ OK bash: GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
 - ✅ OK sh: Ok

 mason.nvim [Languages]
 - ✅ OK cargo: cargo 1.86.0
 - ⚠️ WARNING Composer: not available
   - ADVICE:
     - spawn: composer failed with exit code - and signal -. Could not find executable "composer" in PATH.

 - ⚠️ WARNING PHP: not available
   - ADVICE:
     - spawn: php failed with exit code - and signal -. Could not find executable "php" in PATH.

 - ✅ OK Ruby: ruby 3.4.3 (2025-04-14 revision d0b7e5b6a0) +PRISM [x86_64-linux]
 - ✅ OK luarocks: /home/linuxbrew/.linuxbrew/bin/luarocks 3.11.1
 - ✅ OK Go: go version go1.24.2 linux/amd64
 - ✅ OK node: v23.11.0
 - ⚠️ WARNING julia: not available
   - ADVICE:
     - spawn: julia failed with exit code - and signal -. Could not find executable "julia" in PATH.

 - ✅ OK RubyGem: 3.6.5
 - ✅ OK python: Python 3.13.3
 - ✅ OK java: openjdk version "23.0.2" 2025-01-21
 - ✅ OK npm: 11.3.0
 - ✅ OK javac: javac 23.0.2
 - ✅ OK pip: pip 25.0.1 from /home/username/.local/lib/python3.13/site-packages/pip (python 3.13)
 - ✅ OK python venv: Ok

Screenshots

I suggest having another message like please check that user=false in pip.conf
Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant