Uncaught ReferenceError: require is not defined means CommonJS's require() function was called in a context that doesn't have it — most commonly a browser (which never had require natively) or a Node.js ES module context (where require isn't available by default), and the fix depends entirely on which of those two situations you're actually in.
This error means code written expecting CommonJS's module system (require/module.exports) is running in an environment using a different module system — either genuinely in a browser (which uses import/export or plain script tags, never require), or in Node.js running as an ES module (type: "module" in package.json, or a .mjs file), where require isn't a global by default.
Why This Error Happens
require is specifically a CommonJS/Node.js runtime global, injected by Node's module loader for CommonJS files — it was never part of the JavaScript language specification itself and doesn't exist in browsers, and it's also not automatically available in Node.js ES modules, which use import/export instead. This error surfaces whenever code assuming CommonJS availability runs in a context lacking it.
Reproducing the Error
CommonJS-style code accidentally shipped to the browser:
// Some bundled or copy-pasted code assuming Node.js CommonJS
const lodash = require("lodash");
// Uncaught ReferenceError: require is not defined
// (running directly in a browser, which never has this global)
require used inside a Node.js ES module:
// package.json
{ "type": "module" }
// index.mjs (or any .js file, given "type": "module" above)
const fs = require("fs");
// ReferenceError: require is not defined in ES module scope
Core Concepts Behind This Error
In the browser, this almost always means either unbundled CommonJS code was served directly, or a bundler misconfiguration produced output still containing require() calls — modern bundlers (webpack, esbuild, Vite) are meant to resolve and inline require()/import calls into browser-compatible output, so seeing this error in shipped browser code usually points to a build configuration issue rather than something to patch at the code level.
In Node.js, require is available by default only in CommonJS files — files without "type": "module" in the nearest package.json, or with a .cjs extension; ES module files (.mjs, or .js under "type": "module") need import instead, or can access require-like functionality via createRequire from the module package when genuinely necessary.
Some npm packages are published as CommonJS-only and don't have a native ESM build, meaning importing them from an ES module context requires Node's interop handling (which usually works transparently via import) rather than manually calling require, which isn't available in that context at all.
Client-side code depending on Node.js built-ins or require typically indicates code that should not be running in the browser at all — server-only logic accidentally included in a client bundle, which is a build/bundling configuration issue to fix at the source, not something to patch by polyfilling require in the browser.
Fixing "require Is Not Defined"
Fix 1: In the browser, replace require() with import (ESM) or ensure your bundler is actually processing the file rather than serving it raw:
// Instead of:
const lodash = require("lodash");
// Use ESM import:
import lodash from "lodash";
Fix 2: In a Node.js ES module, replace require() with import:
// index.mjs
import fs from "fs";
Fix 3: If you genuinely need require-like behavior inside a Node.js ES module (for dynamic, conditional requiring), use createRequire:
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const legacyPackage = require("some-cjs-only-package");
Fix 4: If server-only code is leaking into a client bundle, fix the actual import boundary rather than trying to make require work in the browser:
// Ensure server-only modules aren't imported from client-side entry points;
// in Next.js, use the "server-only" package to catch this at build time:
import "server-only";
Should You Ever Polyfill require in the Browser?
No — require synchronously reads files from a filesystem, which doesn't exist in a browser context in any meaningful, general sense; a genuine polyfill isn't really possible for the general case. The correct fix is always either converting the code to use import/bundler-resolved modules, or ensuring your bundler actually processes the file (resolving and inlining its dependencies) rather than serving raw CommonJS source directly to the browser.
Preventing This Error in Production
Keep server-only and client-facing code clearly separated at the module/import-boundary level, using tooling (like Next.js's server-only package) to catch accidental leakage at build time rather than at runtime in the browser. For Node.js projects, be deliberate and consistent about "type": "module" in package.json and understand its implications for require availability before mixing module systems within the same project.
If you hit this error, first determine whether you're in a browser or a Node.js ES module context — the two situations need entirely different fixes, and neither is solved by trying to make require itself available where it fundamentally doesn't belong.