How to Upgrade Node.js on macOS

Updating Node.js on a macOS system is a frequent task for developers. However, situations can arise where, after installing a newer version, the system continues to report or use an older version when checked via the node -v command.

This often occurs when the update method conflicts with a previous installation or system path configurations prioritize an older binary.

This article outlines several effective methods derived from common practices for upgrading Node.js on macOS, helping to ensure the desired version becomes active.

We will explore approaches using the official installer, package managers like Homebrew, and dedicated Node version managers such as ‘n’ and NVM.

Understanding the Version Persistence Problem

The core reason for seeing an old Node.js version after an attempted upgrade often relates to the system’s PATH environment variable. This variable dictates the sequence of directories the shell searches to find executable programs. If an older Node.js executable resides in a directory listed earlier in the PATH than the location of the newly installed version, the system will find and execute the older one first.

Different installation methods place Node.js binaries and manage system paths differently:

  • Direct .pkg Installers: Typically place binaries in locations like /usr/local/bin/. Newer installers generally handle path precedence correctly, but conflicts can arise if older versions installed via other means exist elsewhere in the path.
  • Homebrew: Installs packages into its own structure (e.g., /usr/local/Cellar or /opt/homebrew/Cellar on ARM) and uses symbolic links (symlinks) in a primary path directory (e.g., /usr/local/bin or /opt/homebrew/bin).
  • Version Managers (n, NVM): Install Node.js versions into dedicated directories (often within the user’s home directory) and dynamically modify the PATH for the current shell session or globally via shell profile configuration to point to the chosen version.

Using inconsistent methods or having remnants of old installations can lead to these path conflicts. Sometimes, explicitly removing the older version before installing the new one might be necessary, particularly with manual installations.

Read: How to Fix `dyld: Library not loaded: icu4c` Errors on macOS After Homebrew Operations

Solutions for Upgrading Node.js on macOS

Several reliable methods exist for managing Node.js versions on macOS. Choose the one that best fits your setup and workflow.

Solution 1: Using the Official Node.js Installer (.pkg)

For many users, particularly those who initially installed Node.js this way, downloading and running the latest installer package from the official Node.js website is sufficient.

  1. Navigate to the Node.js website.
  2. Download the macOS Installer (.pkg file) for the desired version (Latest Features or LTS – Long Term Support).
  3. Run the downloaded installer package and follow the prompts.

Modern installers are designed to place the node and npm binaries in /usr/local/bin and ensure this location is correctly prioritized in the system’s path, effectively overwriting compatible previous installations made via the same method. This method also updates npm concurrently.

Verification:

node -v
npm -v

Solution 2: Using Homebrew

If Node.js was originally installed using the Homebrew package manager, it’s best practice to use Homebrew for upgrades.

Steps:

  1. Update Homebrew’s package list:
    brew update
  2. Upgrade the Node.js package:
    brew upgrade node
  3. Optionally, ensure npm is also updated to the latest version (sometimes recommended separately by Homebrew):
    npm install -g npm@latest

    Or simply:

    npm install -g npm

This sequence can be combined into a single command:

brew update && brew upgrade node && npm install -g npm

If Node.js wasn’t installed via Homebrew previously, you can install the latest version using:

brew install node

How it works: Homebrew manages the installation files and updates the necessary symlinks in your path (typically /usr/local/bin on Intel Macs or /opt/homebrew/bin on ARM Macs).

Read: How to Locate the Java Installation Directory on macOS

Considerations: Avoid mixing package managers (like Homebrew and MacPorts). Note that brew upgrade node usually installs the “Current” release branch, not necessarily the LTS version unless specified differently or if only LTS is available via the formula.

Verification:

node -v

Installation Methods Comparison

Solution 3: Using ‘n’ Node Version Manager

‘n’ is a lightweight Node.js version manager installable via npm. It allows for easy switching between installed Node.js versions.

Steps:

  1. Install ‘n’ globally using npm (use sudo if required by your npm permissions setup):
    sudo npm install -g n

    Note: Using sudo with npm global installs should be done cautiously; configure npm permissions properly if possible to avoid needing sudo.

  2. Optional: Clean the npm cache (sometimes suggested, may not always be necessary):
    sudo npm cache clean -f
  3. Install and switch to the desired Node.js version:
    • For the latest stable release:
      sudo n stable
    • For the absolute latest release (including potentially unstable features):
      sudo n latest
    • For the latest Long Term Support (LTS) release:
      sudo n lts
    • For a specific version (e.g., 18.17.1):
      sudo n 18.17.1

Alternatively, you can use npx to run ‘n’ without a global installation:

sudo npx n stable  # Or latest, lts, specific version

How it works: ‘n’ installs Node versions to a central location and manages symlinks to make the selected version active.

Considerations: If the version change isn’t reflected immediately after running the command, try opening a new terminal window or, in some cases, restarting the system.

Verification:

node -v

Solution 4: Using NVM (Node Version Manager)

NVM (Node Version Manager) is another popular tool that allows managing multiple Node.js versions side-by-side.

Installation (if not already installed):

  1. Run the install script (check the official NVM repository for the latest version/command):
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash

    (Replace `v0.39.1` with the current version if necessary).

  2. Follow the script’s output instructions to add NVM sourcing lines to your shell profile (e.g., ~/.bash_profile, ~/.zshrc, ~/.profile, or ~/.zprofile). This typically involves adding lines similar to:
    export NVM_DIR="$HOME/.nvm"
    [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
    [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # Optional: loads nvm bash_completion
  3. Close and reopen your terminal or source your profile file (e.g., source ~/.zshrc).
  4. Verify installation:
    command -v nvm

    (Should output ‘nvm’).

Upgrading/Installing Versions with NVM:

  • Install the latest Node.js release:
    nvm install node
  • Install the latest LTS release:
    nvm install --lts
  • Install a specific version (e.g., 16.20.0):
    nvm install 16.20.0
  • Install a version and migrate global packages from the previously active version:
    nvm install node --reinstall-packages-from=node

    (Replace the second `node` with a specific version like `16.20.0` if migrating from that version).

  • Switch to an installed version for the current shell session:
    nvm use 18.17.0
  • List installed versions:
    nvm ls
  • List available versions for installation:
    nvm ls-remote

NVM will install Node versions into the ~/.nvm directory and modifies the PATH environment variable for the current shell to point to the selected version’s binaries.

Considerations: Installing NVM via Homebrew is generally discouraged by the NVM maintainers. Ensure the NVM sourcing lines are correctly added to your shell profile to work across terminal sessions.

Verification:

node -v
npm -v

Version Manager Comparison

Conclusion

Experiencing issues where an older version of Node.js persists after an upgrade attempt on macOS is often due to path conflicts arising from different or inconsistent installation methods.

Utilizing a dedicated version manager like ‘n’ or NVM provides the most flexibility and robustness for handling multiple Node.js versions without system-wide conflicts. Alternatively, consistently using a single method, such as the official .pkg installer or the Homebrew package manager (if initially used for installation), can also lead to successful upgrades.

Always verify the active version using node -v in a new terminal session after performing an upgrade.

 

Akil Sharma

Akil is a dedicated Cybersecurity Analyst with a strong focus on both offensive and defensive security techniques across Linux and Windows platforms. He delves into topics like vulnerability assessment, penetration testing methodologies, malware analysis, incident response, and implementing security frameworks. Akil is committed to educating readers on the latest threats and sharing actionable strategies for hardening systems and protecting data.