Skip to main content

How to Resolve Python Error "ValueError: invalid mode: 'rU' while trying to load binding.gyp" (node-gyp)

When installing Node.js packages that require compiling native addons using node-gyp (a common build tool), you might encounter a Python error: ValueError: invalid mode: 'rU' while trying to load binding.gyp (or similar). This specific error became prevalent with the release of Python 3.11 and signifies an incompatibility between older node-gyp internal scripts and changes in Python 3.11's file handling.

This guide explains the cause of this error and provides the most effective solutions, including patching node-gyp or managing your Python version.

Understanding the Error: The 'rU' File Mode

In older versions of Python (including Python 2 and early Python 3 versions), the open() function accepted a mode flag 'U' (for "Universal Newlines"). When used with read mode ('rU' or 'U'), it enabled a feature where different line ending conventions (\n used by Linux/macOS, \r\n used by Windows, older \r) were automatically translated into the standard Python newline character (\n) upon reading.

The Cause: Removal of 'U' Mode in Python 3.11+

The 'U' mode was deprecated in Python 3 and completely removed in Python 3.11. Attempting to use 'rU' (or just 'U') as a file opening mode in Python 3.11 or newer raises the ValueError: invalid mode: 'rU'.

The node-gyp tool internally uses Python scripts (part of the gyp build system it bundles) to process project files like binding.gyp. Older versions of these internal scripts contained calls like open(..., 'rU'). When node-gyp is invoked by npm (or yarn) and it uses a Python 3.11+ interpreter, these internal scripts fail with the ValueError.

This is often the most direct fix as it addresses the source of the incompatibility without requiring changes to your Python version. It involves making a small edit to one of node-gyp's internal Python files.

Locating the input.py File

The exact location depends on how Node.js, npm, and node-gyp were installed (globally, via nvm, within a project). Common locations include:

  • Windows (Typical Global npm): C:\Users\YOUR_USERNAME\AppData\Roaming\npm\node_modules\node-gyp\gyp\pylib\gyp\input.py or sometimes within C:\Program Files\nodejs\node_modules\npm\...
  • macOS (Homebrew Node/npm): /opt/homebrew/lib/node_modules/node-gyp/gyp/pylib/gyp/input.py (Apple Silicon) or /usr/local/lib/node_modules/node-gyp/gyp/pylib/gyp/input.py (Intel)
  • macOS/Linux (nvm - Node Version Manager): ~/.nvm/versions/node/YOUR_NODE_VERSION/lib/node_modules/node-gyp/gyp/pylib/gyp/input.py
  • Linux (Typical Global npm): /usr/lib/node_modules/node-gyp/gyp/pylib/gyp/input.py or /usr/local/lib/node_modules/node-gyp/gyp/pylib/gyp/input.py

Tips for finding it:

  • Search your user's global node_modules directory.
  • Search within your Node.js installation directory.
  • If using nvm, look inside the active version's directory.
  • On Linux/macOS: find ~ /usr /opt -name input.py 2>/dev/null | grep 'node-gyp/gyp/pylib/gyp/input.py' (might take time). Use locate pylib/gyp/input.py if your locate database is up-to-date.

Applying the Fix

  1. Open the located input.py file in a text editor (you might need administrator/sudo privileges).
  2. Search for the line containing open(build_file_path, 'rU'). It's usually inside a function like LoadOneBuildFile or similar.
  3. Change this line:
    # Find this line:
    # build_file_contents = open(build_file_path, 'rU').read() # ⛔️ Incorrect for Python 3.11+

    # Change it to remove the 'U':
    build_file_contents = open(build_file_path, 'r').read() # ✅ Correct
  4. Save the input.py file.
  5. Retry your npm install or build command.

This simple change removes the invalid mode flag, making the script compatible with Python 3.11+.

Solution 2: Use Python 3.10 or Earlier

Since the 'U' mode was removed in 3.11, using an earlier version of Python where 'rU' was still functional (though deprecated) will bypass the error.

Checking Your Python Version

python --version
# or
python3 --version
# or (on Windows)
py --version

If the output is 3.11.x or higher, this is likely the cause.

Downgrading/Installing Python 3.10

  • Official Installer: Download Python 3.10.x from the official python.org downloads page and install it. Make sure your system's PATH prioritizes this version, or explicitly point node-gyp to it (see Solution 3).
  • Conda: If using Anaconda/Miniconda, create or update an environment to use Python 3.10:
    # Create a new environment with Python 3.10
    conda create --name py310_env python=3.10
    conda activate py310_env

    # Or install 3.10 into an existing active environment (use with care)
    # conda install python=3.10
  • Homebrew (macOS):
    brew install [email protected]
    # You might need to link it or point node-gyp to it (see Solution 3)

Solution 3: Point node-gyp to a Compatible Python Version

If you have both Python 3.11+ and an older version (like 3.10) installed, you can tell node-gyp to specifically use the older, compatible version without changing your system's default Python.

  • Using npm config (Most Persistent):
    1. Find the full path to your Python 3.10 executable.
      • Linux/macOS examples: /usr/bin/python3.10, /usr/local/bin/python3.10, /opt/homebrew/opt/[email protected]/bin/python3.10
      • Windows example: C:\Users\YourUser\AppData\Local\Programs\Python\Python310\python.exe, C:\Python310\python.exe
    2. Set the configuration:
      npm config set python /full/path/to/your/python3.10
      # Example macOS Homebrew:
      # npm config set python /opt/homebrew/opt/[email protected]/bin/python3.10
      # Example Windows:
      # npm config set python C:\Python310\python.exe
  • Using Environment Variables (Temporary/Session-based):
    # Linux/macOS (Bash/Zsh)
    export npm_config_python=/full/path/to/your/python3.10
    # Or sometimes needed:
    export PYTHON=/full/path/to/your/python3.10

    # Windows Command Prompt
    set npm_config_python=C:\Path\To\Python310\python.exe

    # Windows PowerShell
    $env:npm_config_python = "C:\Path\To\Python310\python.exe"
    Set the variable before running npm install.
  • Using npm install --python=... flag (Per-Command):
    npm install --python=/full/path/to/your/python3.10

Solution 4: Update node-gyp (May or May Not Help)

While the core issue was in the bundled gyp scripts, newer versions of node-gyp might eventually bundle a fixed version of gyp. You can try updating node-gyp, though historically patching (Solution 1) or using an older Python (Solution 2/3) has been more immediately effective.

# Update global node-gyp
npm install -g node-gyp@latest

# Update node-gyp potentially installed via npm dependencies (use with care)
# (This command attempts to find and update all node-gyp instances under ~/.nvm)
# find ~/.nvm -type d -name "node-gyp" -exec sh -c 'cd "$(dirname "{}")" && npm i node-gyp@latest' \;

Conclusion

The ValueError: invalid mode: 'rU' encountered during node-gyp operations is a direct result of Python 3.11+ removing support for the deprecated 'U' (Universal Newlines) file mode used in older node-gyp/gyp internal scripts.

The most effective solutions are:

  1. Patch node-gyp's input.py: Manually edit the file to change 'rU' to 'r'. This directly fixes the incompatibility. (Recommended)
  2. Use Python 3.10 or earlier: Downgrade your active Python version or configure node-gyp (via npm config set python or environment variables) to use a specific Python 3.10 (or older 3.x) executable.

Updating node-gyp itself might help eventually, but patching or managing the Python version provides more immediate control over resolving this specific error.