ReferenceError: x is not defined means JavaScript looked for a variable named x in every scope, from the current block up to the global scope, and found nothing. The usual causes are a typo, a variable declared inside a different block or function, a module you never imported (such as fs), browser globals like window in Node.js, and CommonJS names like require or __dirname inside an ES module. A related message, Cannot access 'x' before initialization, means the variable exists but you used it above its let or const line.
A ReferenceError is different from a TypeError. undefined is a value; "not defined" means there is no variable at all. If the variable exists but holds the wrong thing, you get errors like TypeError: x is not a function instead.
Every error below was produced with Node.js v24.22.1, and the main ones were checked again in headless Chrome 156. Stack trace lines starting with at are trimmed.
In this guide:
- Cause 1: A typo in the variable name
- Cause 2: Using let or const before its line (TDZ)
- Cause 3: The variable lives in a different block
- Cause 4: A Node.js module you never imported
- Cause 5: require is not defined in ES module scope
- Cause 6: __dirname and exports in ES modules
- Cause 7: window or document in Node.js (and SSR)
- Cause 8: Implicit globals in strict mode
- Cause 9: Function expressions are not hoisted like declarations
- Cause 10: $ or another library is not loaded
- Same errors in the browser
- The fixes in one file
- Frequently asked questions
Cause 1: A typo in the variable name
const userName = "Ana";
console.log(username);
c01_typo.cjs:2
console.log(username);
^
ReferenceError: username is not defined
JavaScript names are case-sensitive, so userName and username are different variables. The caret points at the exact name. Search the file for the declaration and copy its spelling. Editors with TypeScript checking, even in plain .js files, underline this before you run the code. My free tools page has browser-based helpers for quick checks like this.
Cause 2: Using let or const before its line (TDZ)
console.log(total);
let total = 10;
c02_tdz.cjs:1
console.log(total);
^
ReferenceError: Cannot access 'total' before initialization
Variables declared with let, const and class exist from the start of their block, but you cannot touch them until the declaration line runs. That gap is the temporal dead zone. var would have printed undefined instead. The fix is to move the declaration above its first use. My post on var vs let vs const covers hoisting in more detail.
Cause 3: The variable lives in a different block
if (true) {
const message = "inside";
}
console.log(message);
c03_block_scope.cjs:4
console.log(message);
^
ReferenceError: message is not defined
let and const are block-scoped, so message only exists inside the if braces. The same applies to variables declared inside a function, a loop, or a try block that you use in the catch. Declare the variable in the outer scope and assign it inside the block (see the fixes file at the end).
Cause 4: A Node.js module you never imported
const text = fs.readFileSync("notes.txt", "utf8");
c04_missing_require.cjs:1
const text = fs.readFileSync("notes.txt", "utf8");
^
ReferenceError: fs is not defined
Built-in modules such as fs, path and os are not globals. Import them first with const fs = require("node:fs") in CommonJS or import fs from "node:fs" in an ES module. Code copied from a tutorial often skips the import line at the top.
Cause 5: require is not defined in ES module scope
const path = require("node:path");
console.log(path.join("a", "b"));
esm/c05_require.js:1
const path = require("node:path");
^
ReferenceError: require is not defined in ES module scope, you can use import instead
This file is being treated as an ES module because it has a '.js' file extension and 'esm/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
Node.js treats a .js file as an ES module when the nearest package.json has "type": "module", or when the file ends in .mjs. ES modules have no require. Node prints a helpful hint after the error. You can switch to import, rename the file to .cjs, or create a require function (shown below). In the browser, Chrome prints just require is not defined, because browsers never had require.
The opposite mistake, an import in a CommonJS file, gives Cannot use import statement outside a module.
Cause 6: __dirname and exports in ES modules
console.log(__dirname);
esm/c06_dirname.js:1
console.log(__dirname);
^
ReferenceError: __dirname is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and 'esm/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
exports.sum = (a, b) => a + b;
esm/c11_exports.js:1
exports.sum = (a, b) => a + b;
^
ReferenceError: exports is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and 'esm/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
__dirname, __filename, exports and module are injected into CommonJS files only. Here are the ES module replacements, all tested:
import path from "node:path";
import { fileURLToPath } from "node:url";
import { createRequire } from "node:module";
console.log(path.join("a", "b"));
console.log(import.meta.dirname === path.dirname(fileURLToPath(import.meta.url)));
const require = createRequire(import.meta.url);
console.log(typeof require("node:os").platform());
export const sum = (a, b) => a + b;
a/b
true
string
import.meta.dirname is available in current Node.js releases, and path.dirname(fileURLToPath(import.meta.url)) works on older ones. Both are described in the Node.js ES modules documentation.
Cause 7: window or document in Node.js (and SSR)
const width = window.innerWidth;
c07_window.cjs:1
const width = window.innerWidth;
^
ReferenceError: window is not defined
window, document and localStorage exist only in browsers. You see this in Node scripts, tests, and in server-side rendering in frameworks like Next.js, where component code runs on the server first. Guard it with typeof, which never throws for undeclared names:
console.log(typeof notDeclaredAnywhere);
console.log(typeof window === "undefined" ? "running in Node" : "running in a browser");
console.log("window" in globalThis, "process" in globalThis);
undefined
running in Node
false true
In React, move browser-only code into useEffect, which runs only in the browser. Use globalThis when you need the global object in any environment.
Cause 8: Implicit globals in strict mode
count = 1;
console.log("sloppy mode created a global:", globalThis.count);
sloppy mode created a global: 1
count = 1;
console.log(count);
esm/c08_implicit_global.js:1
count = 1;
^
ReferenceError: count is not defined
The same two lines behave differently. In a sloppy-mode CommonJS script, assigning to an undeclared name silently creates a global. ES modules and classes are always in strict mode, so the same assignment throws. That is why old code can break when you convert it to modules. Add let or const.
Cause 9: Function expressions are not hoisted like declarations
console.log(add(2, 3));
function add(a, b) { return a + b; }
console.log(multiply(2, 3));
const multiply = (a, b) => a * b;
5
c09_function_expr.cjs:3
console.log(multiply(2, 3));
^
ReferenceError: Cannot access 'multiply' before initialization
add is a function declaration, so it works above its line. multiply is an arrow function stored in a const, so it follows the TDZ rule from cause 2. Either define arrow functions before you call them, or use a function declaration.
Cause 10: $ or another library is not loaded
$(".button").hide();
c10_jquery.cjs:1
$(".button").hide();
^
ReferenceError: $ is not defined
$ is not defined, React is not defined or google is not defined mean the library's script has not run yet. Check that its <script> tag comes before yours, that the CDN URL loads (look at the Network tab), and that an ad blocker is not stopping it. With bundlers, import the library instead of relying on a global.
Same errors in the browser
Chrome 156.0.8078.47
username -> ReferenceError: username is not defined
(() => { console.log(t); let t = 1; })() -> ReferenceError: Cannot access 't' before initialization
require('fs') -> ReferenceError: require is not defined
$('.x') -> ReferenceError: $ is not defined
Chrome uses the same V8 engine as Node.js, so the messages match, except that the require message has no ES module hint. Firefox words some of them differently, but the MDN page for this error lists the causes for all browsers.
The fixes in one file
const fs = require("node:fs");
fs.writeFileSync("/tmp/notes.txt", "hello");
console.log(fs.readFileSync("/tmp/notes.txt", "utf8"));
let message;
if (true) {
message = "inside";
}
console.log(message);
let total = 10;
console.log(total);
hello
inside
10
| Message | Usual cause | Fix |
|---|
x is not defined | Typo, wrong scope, or never declared | Fix the name or declare it in an outer scope |
Cannot access 'x' before initialization | let/const/class used above its line (TDZ) | Move the declaration up |
fs is not defined | Node module used without require/import | const fs = require("node:fs") |
window / document is not defined | Browser code running in Node or during SSR | Check typeof window or run it in the browser |
require is not defined in ES module scope | CommonJS code in an ES module | import or createRequire() |
__dirname is not defined in ES module scope | CommonJS variable in an ES module | import.meta.dirname |
exports is not defined in ES module scope | module.exports style in an ES module | export |
$ is not defined | jQuery not loaded, or loaded after your script | Load the library first |
Missing packages are a different problem: require("lodash") without installing it gives Error: Cannot find module, not a ReferenceError.
Frequently asked questions
What does ReferenceError: x is not defined mean?
JavaScript could not find any variable named x in the current scope or any outer scope. It was never declared, was misspelled, or was declared in a different block or file.
What is the difference between not defined and undefined?
undefined is a value a declared variable can hold. Not defined means no variable with that name exists, and reading it throws a ReferenceError.
What does Cannot access before initialization mean?
The variable is declared with let, const or class, but you used it above the declaration line, inside the temporal dead zone. Move the declaration up.
How do I fix require is not defined in ES module scope?
Use import instead, rename the file to .cjs, or create require with createRequire(import.meta.url) from node:module.
How do I get __dirname in an ES module?
Use import.meta.dirname in current Node.js, or path.dirname(fileURLToPath(import.meta.url)) on older versions.
How do I fix window is not defined in Next.js?
Code that touches window ran on the server. Move it into useEffect, or guard it with typeof window !== "undefined".
How can I check if a variable exists without an error?
Use typeof: typeof name === "undefined" does not throw even when name was never declared, except inside its own TDZ.
Last checked: 9 November 2026. Figures, settings and guidance can change, so confirm anything important with the sources linked above.