parcel-bundler/parcel · critical · Error
NodeFS isn't available in the browser
Error message
NodeFS isn't available in the browser
What it means
Thrown unconditionally in the constructor of NodeFS when the browser-specific build is loaded. Parcel ships two implementations of NodeFS: one for Node.js (using the real fs module) and one for browsers (NodeFS.browser.js) that throws immediately. This is a compile-time replacement via Parcel's bundler aliases, not a runtime check.
Source
Thrown at packages/core/fs/src/NodeFS.browser.js:7
// @flow
import type {FileSystem} from '@parcel/types-internal';
// $FlowFixMe[prop-missing] handled by the throwing constructor
export class NodeFS implements FileSystem {
constructor() {
throw new Error("NodeFS isn't available in the browser");
}
}
View on GitHub (pinned to 59484858a1)
Solutions
- Ensure NodeFS is only imported in Node.js contexts — use conditional imports or dynamic imports gated by `typeof window === 'undefined'`.
- Use MemoryFS or OverlayFS for browser-side virtual filesystem operations instead of NodeFS.
- If using a bundler, mark NodeFS as external or provide a browser stub that doesn't throw.
Example fix
// before
import {NodeFS} from '@parcel/fs';
const fs = new NodeFS(); // throws in browser
// after
import {MemoryFS} from '@parcel/fs';
// or use conditional dynamic import:
// const {NodeFS} = typeof window === 'undefined' ? require('@parcel/fs') : {NodeFS: null}; Defensive patterns
Strategy: validation
Validate before calling
// Prevent NodeFS instantiation in browser environments
function createFS() {
if (typeof window !== 'undefined' || typeof process === 'undefined') {
// Browser environment — use MemoryFS
const {MemoryFS} = require('@parcel/fs');
return new MemoryFS();
}
const {NodeFS} = require('@parcel/fs');
return new NodeFS();
} Type guard
// Environment guard
function isBrowser() {
return typeof window !== 'undefined' ||
(typeof process !== 'undefined' && process.type === 'renderer') ||
typeof navigator !== 'undefined' && navigator.userAgent.includes('node') === false;
} Try / catch
try {
const fs = new NodeFS();
} catch (e) {
if (e.message.includes("isn't available in the browser")) {
const {MemoryFS} = require('@parcel/fs');
fs = new MemoryFS();
} else {
throw e;
}
} Prevention
- Use conditional imports gated by environment checks before importing NodeFS.
- Configure your bundler to replace NodeFS with a browser-compatible stub.
- Prefer MemoryFS or OverlayFS for code that may run in both Node and browser contexts.
- Mark server-only modules as external in browser builds.
When it happens
Trigger: Any code path that instantiates `new NodeFS()` in a browser environment. This happens when a library or Parcel internal module that imports NodeFS is bundled for the browser without proper tree-shaking or conditional loading. The import resolves to NodeFS.browser.js via the module resolver.
Common situations: A Parcel plugin is imported into a browser-side preview or playground that doesn't guard the NodeFS import. A test runner configured for jsdom (browser-like) tries to exercise code that depends on NodeFS. A custom bundler config accidentally includes server-only modules in a browser bundle.
Related errors
- IDBCache is only supported in the browser
- Unknown environment feature: ${feature}
- ${path.relative(process.cwd(), source)} is not a file.
- Unknown entry: ${entry}
- Could not find parcel config at ${path.relative(options.proj
AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13).
Data as JSON: /api/errors/ce967d834c007c2e.
Report an issue: GitHub.