Describe the bug
The Vite+ CLI cannot start in a StackBlitz WebContainer.
A minimal project containing only vite-plus@0.3.0 fails when it runs vp --version or vp env current. Both commands exit while loading vite-plus/binding/index.cjs, before Vite+ processes the command.
The platform-specific native binding cannot load in the WebContainer. The generated loader then checks for these WASI bindings:
./vite-plus.wasi.cjs
@voidzero-dev/vite-plus-wasm32-wasi
Neither option is available:
- The published
vite-plus@0.3.0 package contains no local WASI loader or .wasm artifact.
- The npm registry returns 404 for
@voidzero-dev/vite-plus-wasm32-wasi.
Expected: Vite+ loads a compatible WASI binding and runs vp commands in the WebContainer.
Actual: Vite+ exits with Cannot find native binding.
The missing WASI distribution can also be reproduced deterministically on macOS:
NAPI_RS_FORCE_WASI=error ./node_modules/.bin/vp --version
That command reports both missing WASI options:
Error: WASI binding not found and NAPI_RS_FORCE_WASI is set to error
Cause 1:
Error: Cannot find module '@voidzero-dev/vite-plus-wasm32-wasi'
Cause 2:
Error: Cannot find module './vite-plus.wasi.cjs'
Normal macOS execution succeeds with the native binding. The forced command isolates the unavailable WASI distribution; it does not indicate a problem with the macOS native binding.
Source references
The current generated loader documents WASI as its fallback:
|
// NAPI_RS_FORCE_WASI is a tri-state flag: |
|
// unset / any other value → native binding preferred, WASI is only a fallback |
|
// 'true' → prefer WASI, but retain native as a lazy fallback |
|
// 'error' → require WASI without initializing a native fallback |
|
// Treating any non-empty string as truthy (the historical behavior) meant |
|
// NAPI_RS_FORCE_WASI=false, NAPI_RS_FORCE_WASI=0, etc. inadvertently triggered |
|
// the WASI path, causing ENOENT for packages shipped without a .wasi.cjs file. |
|
// |
|
// NAPI_RS_WASI_FLAVOR selects one exact generated flavor and implies strict |
|
// WASI loading. It never crosses into another flavor or falls back to native. |
It first tries the bundled ./vite-plus.wasi.cjs loader and its .wasm artifacts:
|
if (!wasiBindingLoaded && (!__napiWasiFlavorRequested || __napiWasiFlavor === 'wasm32-wasi')) { |
|
let candidateError = null; |
|
let candidateFailed = false; |
|
try { |
|
candidateError = __napiWasiResolveCandidate('./vite-plus.wasi.cjs', false, [ |
|
'./vite-plus.wasm32-wasi.debug.wasm', |
|
'./vite-plus.wasm32-wasi.wasm', |
|
]); |
|
candidateFailed = candidateError !== null; |
|
if (!candidateFailed) { |
|
wasiBinding = require('./vite-plus.wasi.cjs'); |
|
nativeBinding = wasiBinding; |
|
wasiBindingLoaded = true; |
|
} |
|
} catch (err) { |
|
candidateError = err; |
|
candidateFailed = true; |
|
} |
|
if (candidateFailed) { |
|
wasiBindingErrors.push(candidateError); |
|
loadErrors.push(candidateError); |
|
} |
|
} |
It then tries @voidzero-dev/vite-plus-wasm32-wasi:
|
if (!wasiBindingLoaded && (!__napiWasiFlavorRequested || __napiWasiFlavor === 'wasm32-wasi')) { |
|
let candidateError = null; |
|
let candidateFailed = false; |
|
try { |
|
candidateError = __napiWasiResolveCandidate( |
|
'@voidzero-dev/vite-plus-wasm32-wasi', |
|
true, |
|
undefined, |
|
); |
|
candidateFailed = candidateError !== null; |
|
if (!candidateFailed) { |
|
if ( |
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK && |
|
process.env.NAPI_RS_ENFORCE_VERSION_CHECK !== '0' |
|
) { |
|
const bindingPackageVersion = |
|
require('@voidzero-dev/vite-plus-wasm32-wasi/package.json').version; |
|
if (bindingPackageVersion !== '0.3.0') { |
|
throw new Error( |
|
`WASI binding package version mismatch, expected 0.3.0 but got ${bindingPackageVersion}. You can reinstall dependencies to fix this issue.`, |
|
); |
|
} |
|
} |
|
wasiBinding = require('@voidzero-dev/vite-plus-wasm32-wasi'); |
|
nativeBinding = wasiBinding; |
|
wasiBindingLoaded = true; |
|
} |
|
} catch (err) { |
|
candidateError = err; |
|
candidateFailed = true; |
|
} |
|
if (candidateFailed) { |
|
wasiBindingErrors.push(candidateError); |
|
loadErrors.push(candidateError); |
|
} |
|
} |
When WASI is required and neither option can load, it throws the forced-WASI error:
|
if ((forceWasiError || __napiWasiFlavorRequested) && !wasiBindingLoaded) { |
|
const error = new Error( |
|
__napiWasiFlavorRequested |
|
? 'WASI binding for flavor "' + __napiWasiFlavor + '" not found' |
|
: 'WASI binding not found and NAPI_RS_FORCE_WASI is set to error', |
|
); |
|
error.cause = createLoadErrorChain(wasiBindingErrors); |
|
throw error; |
Related findings
This prevents projects that use Vite+ commands from running in StackBlitz WebContainers. The reproduction contains no application code and fails with vp --version alone.
I am not currently planning a PR.
Reproduction
https://stackblitz.com/~/github.com/ueberBrot/vite-plus-webcontainer-repro?file=package.json&terminal=dev
Steps to reproduce
- Open the StackBlitz reproduction.
- Wait for StackBlitz to install the dependencies.
- StackBlitz automatically runs
pnpm run reproduce, which invokes vp --version.
- Observe that Vite+ exits while loading its native binding.
- Run
pnpm run environment in the terminal.
- Observe that
vp env current fails during the same binding-loading step.
To isolate the unavailable WASI distribution on macOS:
- Clone https://github.com/ueberBrot/vite-plus-webcontainer-repro.
- Run
pnpm install.
- Run
pnpm run reproduce:wasi.
- Observe that Vite+ cannot find either
./vite-plus.wasi.cjs or @voidzero-dev/vite-plus-wasm32-wasi.
System Info
StackBlitz WebContainer
$ node --version
v22.22.3
$ pnpm --version
8.15.6
$ pnpm run environment
> vite-plus-webcontainer-repro@0.0.0 environment /home/ueberBrot/vite-plus-webcontainer-repro
> vp env current
ELIFECYCLE Command failed with exit code 1.
Error: Cannot find native binding. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json and node_modules directory.
at Object.eval (/home/ueberBrot/vite-plus-webcontainer-repro/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:882:19)
at Module._compile (node:internal/modules/cjs/loader:160:19302)
at Module._extensions..js (node:internal/modules/cjs/loader:160:20043)
at Module.load (node:internal/modules/cjs/loader:160:17661)
at Module._load (node:internal/modules/cjs/loader:160:15179)
at wrapModuleLoad (node:internal/modules/cjs/loader:160:4199)
at loadCJSModuleWithModuleLoad (node:internal/modules/esm/translators:174:3866)
at _0x504db8.evaluationFunction (node:internal/modules/esm/translators:174:3603)
Node.js v22.22.3
$ pnpm run reproduce
> vite-plus-webcontainer-repro@0.0.0 reproduce /home/ueberBrot/vite-plus-webcontainer-repro
> vp --version
ELIFECYCLE Command failed with exit code 1.
Error: Cannot find native binding. npm has a bug related to optional dependencies (https://github.com/npm/cli/issues/4828). Please try `npm i` again after removing both package-lock.json and node_modules directory.
at Object.eval (/home/ueberBrot/vite-plus-webcontainer-repro/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:882:19)
at Module._compile (node:internal/modules/cjs/loader:160:19302)
at Module._extensions..js (node:internal/modules/cjs/loader:160:20043)
at Module.load (node:internal/modules/cjs/loader:160:17661)
at Module._load (node:internal/modules/cjs/loader:160:15179)
at wrapModuleLoad (node:internal/modules/cjs/loader:160:4199)
at loadCJSModuleWithModuleLoad (node:internal/modules/esm/translators:174:3866)
at _0x504db8.evaluationFunction (node:internal/modules/esm/translators:174:3603)
Node.js v22.22.3
Used Package Manager
pnpm
Logs
Local diagnostic environment:
macOS 26.6.2
Architecture: arm64
Node.js v24.18.0
vite-plus v0.3.0
$ NAPI_RS_FORCE_WASI=error node -e 'try { require("./node_modules/vite-plus/binding/index.cjs") } catch (error) { let current = error; let index = 0; while (current) { console.error("Cause " + index + ":"); console.error(current.stack || String(current)); current = current.cause; index += 1; } process.exit(1); }'
Cause 0:
Error: WASI binding not found and NAPI_RS_FORCE_WASI is set to error
at Object.<anonymous> (/private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:870:19)
at Module._compile (node:internal/modules/cjs/loader:1871:14)
at Object..js (node:internal/modules/cjs/loader:2002:10)
at Module.load (node:internal/modules/cjs/loader:1594:32)
at Module._load (node:internal/modules/cjs/loader:1396:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.require (node:internal/modules/cjs/loader:1617:12)
at require (node:internal/modules/helpers:153:16)
at [eval]:1:7
at runScriptInThisContext (node:internal/vm:219:10)
Cause 1:
Error: Cannot find module '@voidzero-dev/vite-plus-wasm32-wasi'
Require stack:
- /private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs
- /private/tmp/vite-plus-webcontainer-repro.9X28Wk/[eval]
at /private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:727:19
at Array.reduce (<anonymous>)
at createLoadErrorChain (/private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:720:17)
at Object.<anonymous> (/private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:875:19)
at Module._compile (node:internal/modules/cjs/loader:1871:14)
at Object..js (node:internal/modules/cjs/loader:2002:10)
at Module.load (node:internal/modules/cjs/loader:1594:32)
at Module._load (node:internal/modules/cjs/loader:1396:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.require (node:internal/modules/cjs/loader:1617:12)
Cause 2:
Error: Cannot find module './vite-plus.wasi.cjs'
Require stack:
- /private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs
- /private/tmp/vite-plus-webcontainer-repro.9X28Wk/[eval]
at /private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:727:19
at Array.reduce (<anonymous>)
at createLoadErrorChain (/private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:720:17)
at Object.<anonymous> (/private/tmp/vite-plus-webcontainer-repro.9X28Wk/node_modules/.pnpm/vite-plus@0.3.0_vite@8.2.2/node_modules/vite-plus/binding/index.cjs:875:19)
at Module._compile (node:internal/modules/cjs/loader:1871:14)
at Object..js (node:internal/modules/cjs/loader:2002:10)
at Module.load (node:internal/modules/cjs/loader:1594:32)
at Module._load (node:internal/modules/cjs/loader:1396:12)
at wrapModuleLoad (node:internal/modules/cjs/loader:255:19)
at Module.require (node:internal/modules/cjs/loader:1617:12)
Validations
Describe the bug
The Vite+ CLI cannot start in a StackBlitz WebContainer.
A minimal project containing only
vite-plus@0.3.0fails when it runsvp --versionorvp env current. Both commands exit while loadingvite-plus/binding/index.cjs, before Vite+ processes the command.The platform-specific native binding cannot load in the WebContainer. The generated loader then checks for these WASI bindings:
./vite-plus.wasi.cjs@voidzero-dev/vite-plus-wasm32-wasiNeither option is available:
vite-plus@0.3.0package contains no local WASI loader or.wasmartifact.@voidzero-dev/vite-plus-wasm32-wasi.Expected: Vite+ loads a compatible WASI binding and runs
vpcommands in the WebContainer.Actual: Vite+ exits with
Cannot find native binding.The missing WASI distribution can also be reproduced deterministically on macOS:
That command reports both missing WASI options:
Normal macOS execution succeeds with the native binding. The forced command isolates the unavailable WASI distribution; it does not indicate a problem with the macOS native binding.
Source references
The current generated loader documents WASI as its fallback:
vite-plus/packages/cli/binding/index.cjs
Lines 733 to 742 in d3bc20a
It first tries the bundled
./vite-plus.wasi.cjsloader and its.wasmartifacts:vite-plus/packages/cli/binding/index.cjs
Lines 807 to 829 in d3bc20a
It then tries
@voidzero-dev/vite-plus-wasm32-wasi:vite-plus/packages/cli/binding/index.cjs
Lines 830 to 865 in d3bc20a
When WASI is required and neither option can load, it throws the forced-WASI error:
vite-plus/packages/cli/binding/index.cjs
Lines 869 to 876 in d3bc20a
Related findings
vite-plus-coreandvite-plus. This report concerns the unavailable WASI distribution for the Vite+ CLI itself.This prevents projects that use Vite+ commands from running in StackBlitz WebContainers. The reproduction contains no application code and fails with
vp --versionalone.I am not currently planning a PR.
Reproduction
https://stackblitz.com/~/github.com/ueberBrot/vite-plus-webcontainer-repro?file=package.json&terminal=dev
Steps to reproduce
pnpm run reproduce, which invokesvp --version.pnpm run environmentin the terminal.vp env currentfails during the same binding-loading step.To isolate the unavailable WASI distribution on macOS:
pnpm install.pnpm run reproduce:wasi../vite-plus.wasi.cjsor@voidzero-dev/vite-plus-wasm32-wasi.System Info
Used Package Manager
pnpm
Logs
Validations