dotnet/runtime · error · Error
NodeJS at ' ' has too low version ' ', please use at least .
Error message
NodeJS at '${process.execPath}' has too low version '${process.versions.node}', please use at least ${minNodeVersion}. What it means
Thrown by detect_features_and_polyfill in polyfills.ts when running under NodeJS and process.versions.node (major) is below 14. The runtime relies on NodeJS APIs that exist only in Node 14+; older versions are rejected outright during environment detection.
Solutions
- Upgrade to NodeJS 14 or newer (18+ recommended for native fetch).
- Update the CI Docker image / runner to a current Node LTS.
- If you cannot upgrade Node, this runtime is not supported there.
Example fix
# before: node 12 node --version # v12.x # after: upgrade to a supported LTS nvm install 18 && nvm use 18
Defensive patterns
Strategy: validation
Validate before calling
// before booting the runtime under Node
const [major] = process.versions.node.split('.').map(Number);
if (major < 14) throw new Error(`Node ${process.versions.node} too old; need >= 14`); Prevention
- Pin CI/local Node to an LTS >= 14 (18+ recommended).
- Document the minimum Node version in your README.
- Fail fast in your bootstrap script with a clearer message than the runtime's.
When it happens
Trigger: Running the dotnet wasm runtime under NodeJS 12 or older; a CI image pinned to an old Node version; a host shell that ships an outdated node binary.
Common situations: Legacy CI runners; corporate environments stuck on Node 12; misreporting node version in an embedded JS engine that mimics process.versions.
Related errors
- Can't use moduleFactory callback of createDotnetRuntime…
- Expected environment variable
- Expected runtimeOptions to be an array of strings
- Expected to be a function
- Failed on mono_wasm_get_dbg_command_info
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/f7f3fbe9940ccbb6.
Report an issue: GitHub.
Appendix: source
Thrown at src/mono/browser/runtime/loader/polyfills.ts:60
const str = String(input).replace(/=+$/, "");
let output = "";
for (let bc = 0, bs = 0, i = 0; i < str.length; i++) {
const c = b64.indexOf(str.charAt(i));
if (c === -1) continue;
bs = bc % 4 ? bs * 64 + c : c;
if (bc++ % 4) output += String.fromCharCode(255 & (bs >> ((-2 * bc) & 6)));
}
return output;
};
}
}
if (ENVIRONMENT_IS_NODE) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore:
const process = await import(/*! webpackIgnore: true */"process");
const minNodeVersion = 14;
if (process.versions.node.split(".")[0] < minNodeVersion) {
throw new Error(`NodeJS at '${process.execPath}' has too low version '${process.versions.node}', please use at least ${minNodeVersion}.`);
}
}
const scriptUrlQuery = /*! webpackIgnore: true */import.meta.url;
const queryIndex = scriptUrlQuery.indexOf("?");
if (queryIndex > 0) {
loaderHelpers.modulesUniqueQuery = scriptUrlQuery.substring(queryIndex);
}
loaderHelpers.scriptUrl = normalizeFileUrl(scriptUrlQuery);
loaderHelpers.scriptDirectory = normalizeDirectoryUrl(loaderHelpers.scriptUrl);
loaderHelpers.locateFile = (path) => {
if ("URL" in globalThis && globalThis.URL !== (URLPolyfill as any)) {
return new URL(path, loaderHelpers.scriptDirectory).toString();
}
if (isPathAbsolute(path)) return path;
return loaderHelpers.scriptDirectory + path;
};View on GitHub (pinned to 60108ba66e)