Skip to content

vp env exec / vp node ignore nodeShimMode: system_first, download a managed runtime (~192 MB) that vp env clean then refuses to remove #3093

Closed

Description

@Kat404

Summary

With nodeShimMode: system_first, vite-plus correctly resolves Node.js to the system runtime for the shims and for vp env current / vp env which. The vp env exec family -- which vp node is a shorthand for -- does not honour that preference: it resolves and downloads a vite-plus managed Node runtime instead.

This is not a matter of preference between two managed versions. It is a divergence between what vite-plus reports and what it dispatches, plus disk growth on a machine that explicitly opted out of Node management.

Expected vs actual

Configuration:

{
  "nodeShimMode": "system_first",
  "packageManagerShimModes": { "bun": "system_first", "npm": "system_first",
                               "pnpm": "system_first", "yarn": "system_first" }
}

What agrees with system_first:

$ node -v
v26.11.1
$ vp env which node
/usr/bin/node
$ vp env current
Node.js:
  Version    26.11.1
  Source     system PATH
  Bin Path   /usr/bin/node
  Mode       system_first

What does not:

$ vp node -v
v24.22.0
$ vp env exec node -v
v24.22.0

vp env exec --help states:

--node <NODE> Node.js version to use (e.g., "20.18.0", "lts", "^20.0.0"). If omitted and command is node/npm/npx or a global package binary, version is resolved automatically (same as shim behavior)

The shim resolves to the system Node, so env exec is not resolving "the same as shim behavior".

Reproduction

Deterministic container, Docker or Podman:

https://gist.github.com/Kat404/0c2bf9a8f0a6942f216a827098e3a24d

podman build -t vp-sysfirst-exec .
podman run --rm vp-sysfirst-exec
CASE A: DIVERGENCE CONFIRMED  shim=v20.19.2  vp-node=v24.22.0
CASE B: 201708991 bytes on disk under js_runtime/node
CASE C: inventory tracks it as: * v24.22.0 current
CASE D: inventory does record it, so uninstall (not clean) is the only removal
CASE E: vp env clean -> ✓ Removed 0 Node.js runtimes

The build fails if the divergence does not reproduce.

Manually, without a container:

vp env off node
vp env off pm
mkdir -p /tmp/repro && cd /tmp/repro
printf '{\n  "name": "repro",\n  "version": "1.0.0",\n  "private": true\n}\n' > package.json
node -v                 # system version
vp env which node       # /usr/bin/node
vp node -v              # vite-plus managed version

Consequences

  1. Unwanted download. Running vp node (or vp env exec node) materialises a managed runtime of roughly 190-220 MB on a machine configured to use the system Node.

  2. vp env clean cannot reclaim it. Once downloaded, the runtime is recorded as the current version:

$ vp env list
Node.js
  * v24.22.0 current

$ vp env clean
✓ Removed 0 Node.js runtimes

Per the docs, vp env clean preserves the current and configured-default versions. So the space comes back every time a project invokes vp node, and the only removal is the explicit vp env uninstall 24.22.0.

  1. Confusing state. vp env list reports * v24.22.0 current while vp env current reports the system 26.11.1 as the resolved environment. Two commands, two different "current" Node runtimes.

Possible fixes

  • Resolve env exec through the same path the shims use, so nodeShimMode: system_first applies to it too.
  • Or: when a runtime is materialised only as an env exec fallback while the environment is system-first, do not record it as the current install, so vp env clean can remove it.

Related, not duplicates

Environment

  • vite-plus v1.3.0 (vp upgrade --check reports already up to date)
  • Arch Linux, kernel 6.x
  • System Node.js: v26.11.1 at /usr/bin/node (pacman nodejs)
  • Container repro: debian:stable-slim with Debian nodejs v20.19.2 at /usr/bin/node, vite-plus installed via curl -fsSL https://vite.plus | bash
  • Podman 6.1.4

Activity

  1. Kat404 commented on Oct 16, 2026

    @Kat404
    Author

    Follow-up: command-by-command matrix, and a distinction that may localise the bug

    I ran the full project command surface in a disposable sandbox with Vite+ 1.3.0 installed through the system package manager, and fingerprinted the runtime each command actually uses instead of inferring it from disk usage.

    A Vite plugin with buildStart() printing process.version and process.execPath gives a definitive runtime fingerprint:

    export default defineConfig({
      plugins: [
        {
          name: 'node-probe',
          buildStart() {
            console.log(`[PROBE] node=${process.version} execPath=${process.execPath}`)
          },
        },
      ],
    })

    Results

    Command Runtime used Honours system_first
    vp dev v26.11.1 (/usr/bin/node) yes
    vp build v26.11.1 (/usr/bin/node) yes
    vp run <task> v26.11.1 (/usr/bin/node) yes
    vp test no download yes
    vp lint no download yes
    vp preview no download yes
    vp exec node -v v26.11.1 yes
    vp env exec node -v v24.22.0 (managed) no
    vp node -v v24.22.0 (managed) no

    Nothing was downloaded by any of the honouring commands: js_runtime stayed at 220394524 bytes and index_cache.json never changed mtime across the whole run.

    The detail that may matter most

    vp exec and vp env exec are similarly named commands with opposite resolution behaviour:

    • vp exec runs a binary from local node_modules/.bin and used the system Node.
    • vp env exec runs a command in the resolved environment and used the managed Node.

    That narrows the search considerably: the shim resolution path used by vp dev, vp build and vp run already honours system_first correctly, so the divergence is specific to the environment-resolution branch reached from vp env exec and its vp node shorthand.

    Correction to a related issue

    I previously read #2642 ("Concurrent vp run dev processes download the same Node.js runtime twice") as suggesting that vp run materialises a managed runtime. That is not reproducible in system_first mode: vp run completed a task that reported node=v26.11.1 execPath=/usr/bin/node and left the store untouched. #2642 presumably covers a managed-mode or first-run scenario.

    One extra observation

    When a runtime download is interrupted, vp leaves its temporary directory behind:

    ~/.local/share/vite-plus/js_runtime/.tmp6Bz2kU/node-v24.22.0-linux-x64.tar.gz
    ~/.local/share/vite-plus/js_runtime/.tmpnTkXLZ/node-v24.22.0-linux-x64.tar.gz
    

    Two partial tarballs, 18 MB, never reclaimed, even after vp env uninstall. This looks like the same class as #1949 ("clean up the temp dir when a package-manager install fails"), but on the js_runtime path rather than the package-manager path.

    Workaround confirmed

    Avoiding vp node and vp env exec entirely keeps the managed runtime out of the picture. When it does land, vp env clean will not remove it, because it is recorded as current:

    vp env uninstall 24.22.0

    Environment

    Same as the original report: Vite+ v1.3.0, Arch Linux, system Node.js v26.11.1, nodeShimMode: system_first, all package-manager shims also system_first. Sandbox: Debian nodejs v20.19.2 at /usr/bin/node, Vite+ installed via the documented curl -fsSL https://vite.plus | bash.

  2. added theissue type on Oct 17, 2026
  3. liangmiQwQ commented on Oct 17, 2026

    @liangmiQwQ
    Collaborator

    It seems introduced in #2758. I'll find a way to fix.

  4. added a commit that references this issue on Oct 18, 2026
    f548ae3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Fields

Priority

None yet

Effort

None yet

Target date

None yet

Start date

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions