parcel-bundler/parcel · error · ThrowableDiagnostic
Node builtin polyfill "${packageName}" is not installed, but
Error message
Node builtin polyfill "${packageName}" is not installed, but auto install is disabled. What it means
Thrown by @parcel/node-resolver-core when a Node builtin (e.g. 'crypto', 'fs', 'path') is imported in a browser/electron-renderer environment, the matching polyfill package is not installed, and auto-install is disabled. The resolver knows the canonical polyfill per builtin (e.g. crypto-browserify) and would auto-install it if shouldAutoInstall were true; otherwise it throws with a documentationURL and a hint to install the package manually.
Source
Thrown at packages/utils/node-resolver-core/src/Wrapper.js:335
this.options.projectRoot + '/index',
{
saveDev: true,
shouldAutoInstall: true,
range: builtin.range,
},
);
// Need to clear the resolver caches after installing the package
this.resolversByEnv.clear();
// Re-resolve
return this.resolve({
...options,
filename: builtin.name,
parent: this.options.projectRoot + '/index',
});
} else {
throw new ThrowableDiagnostic({
diagnostic: {
message: md`Node builtin polyfill "${packageName}" is not installed, but auto install is disabled.`,
codeFrames: options.loc
? [
{
filePath: options.loc.filePath,
codeHighlights: [
convertSourceLocationToHighlight(
options.loc,
'used here',
),
],
},
]
: [],
documentationURL:
'https://parceljs.org/features/node-emulation/#polyfilling-%26-excluding-builtin-node-modules',
hints: [View on GitHub (pinned to 59484858a1)
Solutions
- Install the named polyfill package: `npm install <packageName>` (the message names it, e.g. crypto-browserify).
- Enable auto-install: pass --auto-install or set shouldAutoInstall in the Parcel config.
- If the import is unwanted, alias/exclude the builtin via Parcel's node-emulation config.
- Pin the version range suggested by builtin.range to avoid resolver warnings.
Example fix
// before
import { createHash } from 'crypto'; // browser env, no polyfill, autoInstall off
// after
$ npm install crypto-browserify
// or in .parcelrc/resolve config alias 'crypto' -> 'crypto-browserify' Defensive patterns
Strategy: validation
Validate before calling
const NODE_BUILTINS = new Set(['fs','path','crypto','os','stream','buffer',/*...*/]);
const POLYFILLS = { crypto: 'crypto-browserify', stream: 'stream-browserify', buffer: 'buffer', path: 'path-browserify' /* ... */ };
for (const spec of imports) {
if (NODE_BUILTINS.has(spec) && env.targetsBrowser) {
const pkg = POLYFILLS[spec];
if (!await packageIsInstalled(pkg)) throw new Error(`Install ${pkg} to polyfill Node builtin '${spec}'`);
}
} Type guard
function isNodeBuiltin(spec) {
return new Set(['fs','path','crypto','os','stream','buffer','http','https','zlib','url','util']).has(spec);
} Prevention
- Pre-install browser polyfills for any Node builtin a dependency may import.
- Enable --auto-install in dev to let Parcel fetch polyfills on demand.
- Audit third-party deps for Node-builtin usage before targeting browsers.
When it happens
Trigger: A dependency imports a Node builtin; the target env is browser-like; the polyfill package is absent from node_modules; and this.options.shouldAutoInstall is false. options.loc, if present, is rendered as a codeframe highlighting the import.
Common situations: A browser build pulling in a library that uses Node builtins, Parcel v2 defaulting autoInstall off in CI, or a polyfill package removed during dependency cleanup.
Related errors
- Resolvers must return an absolute path, ${resolver.name} ret
- Library targets are not supported in serve mode.
- Expected package.json file in ${rootDir}
- Unexpected output file type ${ext} in target "${targetName}"
- The "global" output format is not supported in the "${target
AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13).
Data as JSON: /api/errors/b856c8d95919bf72.
Report an issue: GitHub.