dotnet/runtime · error · Error
Using node without crypto support. To enable current…
Error message
Using node without crypto support. To enable current operation, either provide polyfill for 'globalThis.crypto.getRandomValues' or enable 'node:crypto' module.
What it means
initPolyfillsEarly() under Node tries to import('node:crypto'). If that import fails (Node built without OpenSSL, a bundled runtime without the crypto module, or an opaque sandbox blocking dynamic import) it installs a stub for globalThis.crypto.getRandomValues that throws this message when called. The throw is deferred until something actually requests random bytes — typically integrity check, GUID, or TLS within the runtime.
Solutions
- Use a standard Node.js distribution that includes crypto (node:crypto is built-in).
- Provide a polyfill: set globalThis.crypto.getRandomValues to a function that fills the buffer from a CSPRNG before bootstrapping the loader.
- If using a bundler, mark node:crypto as external so the dynamic import resolves at runtime.
- Disable integrity checks (loaderConfig.disableIntegrityCheck=true) if randomness is only consumed by SRI — but other runtime paths still need getRandomValues.
Example fix
// before: node:crypto blocked, getRandomValues throws on first use
// after: provide polyfill before createDotnetRuntime
import { webcrypto } from 'node:crypto';
globalThis.crypto = webcrypto as any;
await dotnet.create(); Defensive patterns
Strategy: validation
Validate before calling
function hasCryptoRandom(): boolean {
return typeof (globalThis as any).crypto?.getRandomValues === 'function';
}
if (!hasCryptoRandom()) {
// install polyfill before bootstrapping
} Type guard
function hasWebCrypto(): boolean {
const c = (globalThis as any).crypto;
return !!c && typeof c.getRandomValues === 'function';
} Try / catch
try { await dotnet.create(); } catch (e) {
if (/crypto support/.test((e as Error).message)) {
const { webcrypto } = await import('node:crypto');
(globalThis as any).crypto = webcrypto;
await dotnet.create();
} else throw e;
} Prevention
- Use a standard Node.js build with OpenSSL included.
- If running under a bundler, mark node:crypto as external.
- Polyfill globalThis.crypto.getRandomValues before createDotnetRuntime in custom hosts.
- Pin the Node version in CI/Dockerfile to one known to ship crypto.
When it happens
Trigger: Running the WASM loader in a Node build that excluded the crypto module (e.g. custom NodeJS build, Electron with --disable-crypto). Sandboxed environments (Cloudflare Workers in Node-compat mode, certain bundlers) that block dynamic import of node:crypto. Node compiled with --without-ssl.
Common situations: Electron main process with a stripped Node. Bun/Deno emulating Node where node:crypto import is partial. A bundler (webpack) that statically resolves the dynamic import to nothing. Container image with a minimal Node that lacks openssl.
Related errors
- No fetch implementation available
- Please install `node-fetch` and `node-abort-controller` npm…
- Missing window to the query parameters from
- No fetch implementation available
- NotImplementedException
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/3780686cde33acb2.
Report an issue: GitHub.
Appendix: source
Thrown at src/native/libs/Common/JavaScript/loader/polyfills.ts:53
}
}
if (ENVIRONMENT_IS_NODE) {
if (!globalThis.crypto) {
globalThis.crypto = <any>{};
}
if (!globalThis.crypto.getRandomValues) {
let nodeCrypto: any = undefined;
try {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore:
nodeCrypto = await import(/*! webpackIgnore: true */"node:crypto");
} catch (err: any) {
// Noop, error throwing polyfill provided bellow
}
if (!nodeCrypto) {
globalThis.crypto.getRandomValues = () => {
throw new Error("Using node without crypto support. To enable current operation, either provide polyfill for 'globalThis.crypto.getRandomValues' or enable 'node:crypto' module.");
};
} else if (nodeCrypto.webcrypto) {
globalThis.crypto = nodeCrypto.webcrypto;
} else if (nodeCrypto.randomBytes) {
const getRandomValues = (buffer: Uint8Array) => {
if (buffer) {
buffer.set(nodeCrypto.randomBytes(buffer.length));
}
};
globalThis.crypto.getRandomValues = getRandomValues as any;
}
}
if (!globalThis.performance) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore:
globalThis.performance = (await import(/*! webpackIgnore: true */"perf_hooks")).performance;
}
}View on GitHub (pinned to 60108ba66e)